{"componentChunkName":"component---src-templates-post-js","path":"/blog/workpad-part-4","webpackCompilationHash":"97000b66fda8dd565841","result":{"data":{"site":{"siteMetadata":{"keywords":["blog","ubug","tech blog","技术博客","playground"]}},"mdx":{"fields":{"title":"🌋 WebIDE 的开发记录其四（命令行终端）","tips":[],"categories":["webide"],"datetime":"2020-01-23 21:45:01","noFooter":false,"description":"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第四篇文章，谈谈命令行终端是怎么集成的。","plainTextDescription":"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第四篇文章，谈谈命令行终端是怎么集成的。\n","author":"Ubug","banner":{"childImageSharp":{"fluid":{"tracedSVG":"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='400'%20height='291'%3e%3cpath%20d='M0%20147v137h313v-35c1-39%200-40-2-40l-1-2c0-2%201-3%202-3l1-15%201-10v-1l-1-7v-6h78v119h10V9H76v20h-5c-4%200-5%200-4-1h-1c-2%201-4%201-4-2l-1-1v3c1%201-4%201-10%201l-8-1c2%200%203-1%203-3s0-2-9-2-9%200-9%202c-1%203%200%203%205%203l-9%201c-14%200-15%200-14-2v-2l-1-5C9%208%2010%209%205%209H0v138M284%2020l-1%201c-2%200-2%202-2%2012v12h28v-6a163%20163%200%20000-13v-7h-13l-12%201m-137%203l2%202%201-1h1c1%201%2050%201%2050-1%200-1-4-2-27-2-26%200-27%200-27%202m171%2014l37%201%2036-1-36-1-37%201M9%2071v3h67v-6H9v3m108%2044v2c-1%202%201%202%2020%202a94%2094%200%200021-1l1-1a2801%202801%200%2000-42-1m-24%2011v3H76v3c0%203%200%203%203%203h103l99%201v-7H94v-3l-1-2v2m244%2015l16%201h-16l-16%201a830%20830%200%200016-2m-218%203l-2%201c0%201%204%202%2017%202%2016%200%2017%200%2017-2l-15-1h-17m-31%2010c-11%200-12%200-12%202s1%202%2096%202h98c1%200%202-1%202-3v-2h-86l-98%201'%20fill='%23573ede'%20fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":1.3726273726273726,"src":"/static/bb64a05fbbe7c7a1e8fb20d74f544712/9679e/WorkPad-demo.png","srcSet":"/static/bb64a05fbbe7c7a1e8fb20d74f544712/82675/WorkPad-demo.png 500w,\n/static/bb64a05fbbe7c7a1e8fb20d74f544712/fef60/WorkPad-demo.png 1000w,\n/static/bb64a05fbbe7c7a1e8fb20d74f544712/9679e/WorkPad-demo.png 1374w","srcWebp":"/static/bb64a05fbbe7c7a1e8fb20d74f544712/3c76f/WorkPad-demo.webp","srcSetWebp":"/static/bb64a05fbbe7c7a1e8fb20d74f544712/7fe04/WorkPad-demo.webp 500w,\n/static/bb64a05fbbe7c7a1e8fb20d74f544712/d619e/WorkPad-demo.webp 1000w,\n/static/bb64a05fbbe7c7a1e8fb20d74f544712/3c76f/WorkPad-demo.webp 1374w","sizes":"(max-width: 1374px) 100vw, 1374px"}}},"bannerCredit":null,"slug":"/blog/workpad-part-4","tags":["思考","整理","WorkPad","WebIDE","云开发","在线编辑器"]},"headings":[{"value":"一、为什么要终端","depth":2},{"value":"二、基础概念","depth":2},{"value":"三、集成","depth":2},{"value":"1. 第一版","depth":3},{"value":"2. 第二版 Docker","depth":3},{"value":"四、docker 进程回收问题","depth":2}],"body":"const _excluded = [\"components\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }\n/* @jsx mdx */\n\nconst _frontmatter = {\n  \"slug\": \"workpad-part-4\",\n  \"title\": \"🌋 WebIDE 的开发记录其四（命令行终端）\",\n  \"date\": \"2020-01-23 21:45:01\",\n  \"author\": \"Ubug\",\n  \"description\": \"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第四篇文章，谈谈命令行终端是怎么集成的。\",\n  \"series\": \"WebIDE 的开发记录\",\n  \"categories\": [\"webide\"],\n  \"tags\": [\"思考\", \"整理\", \"WorkPad\", \"WebIDE\", \"云开发\", \"在线编辑器\"],\n  \"banner\": \"./WorkPad-demo.png\"\n};\nconst makeShortcode = name => function MDXDefaultShortcode(props) {\n  console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n  return mdx(\"div\", props);\n};\nconst WithFigcaption = makeShortcode(\"WithFigcaption\");\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n      components\n    } = _ref,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h2\", null, \"\\u4E00\\u3001\\u4E3A\\u4EC0\\u4E48\\u8981\\u7EC8\\u7AEF\"), mdx(\"p\", null, \"\\u7A0B\\u5E8F\\u5458\\u5BF9\\u7535\\u8111\\u7684\\u63A7\\u5236\\u5927\\u90E8\\u5206\\u8FD8\\u662F\\u9700\\u8981\\u7EC8\\u7AEF\\u7684\\u5E2E\\u52A9\\uFF0C\\u8FD0\\u884C\\u670D\\u52A1\\u3001\\u6267\\u884C\\u4EE3\\u7801\\u3001\\u8C03\\u8BD5\\u7B49\\u7B49\\u64CD\\u4F5C\\u90FD\\u53EF\\u4EE5\\u5728\\u7EC8\\u7AEF\\u4E2D\\u5B8C\\u6210\\uFF0C\\u751A\\u81F3\\u7F16\\u8F91\\u529F\\u80FD\\u4E5F\\u53EF\\u4EE5\\u5728\\u7EC8\\u7AEF\\u4E2D\\u5B9E\\u73B0\\uFF0C\\u8FD0\\u884C\\u73AF\\u5883\\u7684\\u7BA1\\u7406\\u3001\\u6587\\u4EF6\\u3001\\u7A0B\\u5E8F\\u7B49\\u80FD\\u5728\\u7EC8\\u7AEF\\u4E2D\\u64CD\\u4F5C\\u3002\\u4E00\\u822C\\u610F\\u4E49\\u4E0A\\uFF0CIDE \\u548C \\u7F16\\u8F91\\u5668\\u7684\\u6700\\u5927\\u533A\\u522B\\u4E5F\\u662F\\u6709\\u7EC8\\u7AEF\\u529F\\u80FD\\u7684\\u652F\\u6301\\u3002\\u6240\\u4EE5\\u65E5\\u5E38\\u5F00\\u53D1\\u7EC8\\u7AEF\\u662F\\u5FC5\\u4E0D\\u53EF\\u5C11\\u7684\\u4E00\\u4E2A\\u5DE5\\u5177\\uFF0C\\u800C\\u5728 web \\u4E2D\\u4E5F\\u5DF2\\u7ECF\\u6709\\u5F88\\u6210\\u719F\\u7684\\u5DE5\\u5177 Xterm.js\\u3002\"), mdx(\"div\", {\n    style: {\n      display: 'flex',\n      justifyContent: 'center'\n    }\n  }, mdx(WithFigcaption, {\n    title: \"\\u5728\\u7EBF IDE \\u9879\\u76EE\\u4E2D\\u96C6\\u6210\\u7EC8\\u7AEF\\u7684\\u6548\\u679C\",\n    mdxType: \"WithFigcaption\"\n  }, mdx(\"video\", {\n    autoPlay: true,\n    loop: true,\n    controls: true,\n    style: {\n      maxWidth: '100%'\n    }\n  }, mdx(\"source\", {\n    src: \"https://fdb.ubug.io/storybook-videos/term.mp4\",\n    type: \"video/mp4\"\n  })))), mdx(\"h2\", null, \"\\u4E8C\\u3001\\u57FA\\u7840\\u6982\\u5FF5\"), mdx(\"p\", null, \"TTY\\u3001terminal\\u3001Shell\\u3001pty\\u3001bash\\u3001ssh \\u90FD\\u662F\\u4EC0\\u4E48\\uFF1F\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"tty unix\\u7CFB\\u7EDF\\u4E2D\\u8868\\u793A\\u4E3A\\u53EF\\u4EE5\\u8F93\\u5165\\u8F93\\u51FA\\u7684\\u8BBE\\u5907\\uFF0C\\u73B0\\u5728\\u8BF4\\u7684\\u6BD4\\u8F83\\u591A\\u7684\\u662F\\u865A\\u62DF\\u7EC8\\u7AEF\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"terminal \\u8868\\u793A\\u6587\\u672C\\u7684\\u8F93\\u5165\\u8F93\\u51FA\\u73AF\\u5883\\uFF0C\\u4E00\\u4E2A\\u8F93\\u5165\\u548C\\u663E\\u793A\\u8BBE\\u5907\\u7684\\u6982\\u5FF5\\uFF0C\\u8868\\u793A\\u6211\\u4EEC\\u80FD\\u5728\\u7EC8\\u7AEF\\u4E2D\\u8F93\\u5165\\uFF0C\\u7CFB\\u7EDF\\u80FD\\u5728\\u7EC8\\u7AEF\\u4E2D\\u8F93\\u51FA\\uFF0C\\u5F88\\u591A\\u65F6\\u5019\\u4E5F\\u5C31\\u662F\\u8BF4 tty\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Shell \\u662F\\u4E00\\u4E2A\\u547D\\u4EE4\\u884C\\u89E3\\u91CA\\u5668\\uFF0C\\u662F\\u4E00\\u4E2A\\u8F6F\\u4EF6\\uFF0C\\u6839\\u636E\\u6211\\u4EEC\\u5728 terminal \\u7684\\u8F93\\u5165\\u6765\\u8FD0\\u884C\\u7A0B\\u5E8F\\u5E76\\u5C06\\u8F93\\u51FA\\u4EA4\\u7ED9 terminal\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"pty \\u662F \\u865A\\u62DF\\u7EC8\\u7AEF \\u7684\\u6982\\u5FF5\\uFF0C\\u8868\\u793A\\u901A\\u8FC7\\u6A21\\u62DF\\u4E00\\u4E2A\\u8F93\\u5165\\u8F93\\u51FA\\u7684\\u903B\\u8F91\\u63D0\\u4F9B\\u7C7B\\u4F3C tty \\u7684\\u5DE5\\u4F5C\\u673A\\u5236\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"bash \\u662F Shell \\u7A0B\\u5E8F\\u7684\\u4E00\\u79CD\\uFF0C\\u9664\\u6B64\\u4E4B\\u5916\\u8FD8\\u6709 sh\\u3001zsh \\u7B49\\uFF0C\\u8D1F\\u8D23\\u89E3\\u91CA\\u6267\\u884C\\u7EC8\\u7AEF\\u7684\\u5B57\\u7B26\\uFF0C\\u5E76\\u8C03\\u7528\\u7A0B\\u5E8F\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"ssh \\u662F\\u8FDC\\u7A0B\\u4F20\\u8F93\\u534F\\u8BAE\\uFF0C\\u5141\\u8BB8\\u7EC8\\u7AEF\\u901A\\u8FC7\\u8FD9\\u4E2A\\u534F\\u8BAE\\u8FDE\\u63A5\\u670D\\u52A1\\u7AEF\\uFF0C\\u7136\\u540E sshd \\u7A0B\\u5E8F\\u63A5\\u6536\\u6570\\u636E\\u4EA4\\u7ED9 tty / pty\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u8FD8\\u6709 ptmx\\u3001pts\\u3001tmux \\u4E4B\\u7C7B\\u7684\\u6982\\u5FF5\\u548C\\u8FD9\\u65E0\\u5173\\u5C31\\u4E0D\\u6DF1\\u5165\\u4E86\")), mdx(\"p\", null, \"\\u6BD4\\u5982 node-pty \\u901A\\u8FC7\\u5BF9\\u8FDB\\u7A0B\\u7684\\u6302\\u8F7D\\uFF0C\\u63D0\\u4F9B\\u4E00\\u4E2A\\u8F93\\u5165\\u8F93\\u51FA\\u6765\\u6A21\\u62DF\\u7EC8\\u7AEF\\u7684\\u63A5\\u5165\\u3002\"), mdx(\"p\", null, \"\\u7528 websocket \\u6765\\u521B\\u5EFA\\u4E00\\u4E2A\\u8FDE\\u63A5\\u670D\\u52A1\\u7AEF\\u548C\\u5BA2\\u6237\\u7AEF\\u7684\\u901A\\u9053\\uFF0C\\u5C06\\u5BA2\\u6237\\u7AEF\\u7684\\u8F93\\u5165\\u4EA4\\u7ED9 node-pty \\uFF0C\\u5C06 node-pty \\u7684\\u8F93\\u51FA\\u4EA4\\u7ED9\\u5BA2\\u6237\\u7AEF\"), mdx(\"p\", null, \"Xterm.js \\u5728\\u5BA2\\u6237\\u7AEF\\u5B9E\\u73B0\\u4E00\\u4E2A\\u7C7B\\u4F3C \\u7EC8\\u7AEF\\u7684\\u754C\\u9762\\uFF0C\\u7136\\u540E\\u53EF\\u4EE5\\u63A5\\u6536\\u670D\\u52A1\\u7AEF\\u7684\\u8F93\\u51FA\\u4F5C\\u4E3A\\u5BA2\\u6237\\u7AEF\\u8F93\\u51FA\\u663E\\u793A\\uFF0C\\u76F8\\u5E94\\u7528\\u6237\\u7684\\u8F93\\u5165\\u80FD\\u591F\\u4F20\\u7ED9\\u670D\\u52A1\\u7AEF\\u4F5C\\u4E3A\\u8F93\\u5165\\u3002\"), mdx(\"p\", null, \"\\u6700\\u7EC8\\u4E5F\\u5C31\\u5B8C\\u6210\\u4E86\\u6574\\u4E2A\\u7EC8\\u7AEF\\u529F\\u80FD\\u7684\\u6A21\\u62DF\\u3002\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"958px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"27.413127413127413%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsSAAALEgHS3X78AAABH0lEQVQY0z2QTWvCUBBFH34sXIuIkqoJCi6qlSQSmiaxAUHFxBgDSSDtquD//wenmQft4jLz5g2Xe0bZto3v+0jdbDbsdjvde56H67o4jqO1XC61VqsVpmkSxzHX65UgCEiSlPP5zPF4RG23W6bTqV42DIPZbKb7v9l8Pme9XjOZTOh0OiiltBzH5vl8cjqdSNOUoijIsgyVJAn3+52qqsjznKZpqOuay+WiE8hM3o/HA9mVeRCGeP4Hzdc3n4eDNhIPkTJNS2NIEkkkmIK93+91lXRRFBG2JqPRiMFgQL/XI3Hf+KlLguhA3hqVZcntdkMZxovGGQ6HjMfjf3PLslgsFvpPbiun6Ha79Pp9ui1y5bxSxCHvQUjWGgmyEP0CZgygr+cz4mUAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"终端与容器进程的对应\",\n    \"title\": \"终端与容器进程的对应\",\n    \"src\": \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png\",\n    \"srcSet\": [\"/static/e425ecabd045bc5c9d0fd4e844fac542/ae269/term-process.png 259w\", \"/static/e425ecabd045bc5c9d0fd4e844fac542/a4dff/term-process.png 518w\", \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png 958w\"],\n    \"sizes\": \"(max-width: 958px) 100vw, 958px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u7EC8\\u7AEF\\u4E0E\\u5BB9\\u5668\\u8FDB\\u7A0B\\u7684\\u5BF9\\u5E94\"), \"\\n  \")), mdx(\"h2\", null, \"\\u4E09\\u3001\\u96C6\\u6210\"), mdx(\"p\", null, \"Xterm \\u7684\\u96C6\\u6210\\u6CA1\\u82B1\\u591A\\u957F\\u65F6\\u95F4\\uFF0C\\u5F88\\u7B80\\u5355\\uFF0C\\u4E0D\\u8FC7\\u6280\\u672F\\u9009\\u578B\\u6F14\\u8FDB\\uFF0C\\u52A0\\u4E0A\\u5C0F\\u529F\\u80FD\\u4F18\\u5316\\u8FD8\\u662F\\u82B1\\u4E86\\u633A\\u591A\\u7CBE\\u529B\\u3002\"), mdx(\"h3\", null, \"1. \\u7B2C\\u4E00\\u7248\"), mdx(\"p\", null, \"\\u7B2C\\u4E00\\u7248\\u662F\\u901A\\u8FC7 node-pty \\u73B0\\u6210\\u7684 demo \\u76F4\\u63A5\\u8FD0\\u884C\\uFF0C\\u6548\\u679C\\u5F88\\u4E0D\\u9519\\u3002\"), mdx(\"p\", null, \"server \\u7AEF\\u7684\\u90E8\\u5206\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"const os = require('os');\\nconst pty = require('node-pty');\\nconst app = require('express')();\\nconst http = require('http').createServer(app);\\nconst io = require('socket.io')(http);\\n\\n// \\u901A\\u8FC7\\u6302\\u8F7D process \\u6765\\u6A21\\u62DF\\u7EC8\\u7AEF\\u7A0B\\u5E8F\\nconst shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';\\nconst ptyProcess = pty.spawn(shell, [], {\\n  name: 'xterm-demo',\\n  cols: 80,\\n  rows: 30,\\n  cwd: process.env.HOME,\\n  env: process.env\\n});\\n\\n// \\u901A\\u8FC7 socket.io \\u6765\\u8F93\\u5165\\u8F93\\u51FA\\nio.on('connection', (socket) => {\\n  socket.on('_term_write_in', (msg) => {\\n    ptyProcess.write(`${msg}\\\\r`);\\n  });\\n  socket.on('_term_resize', (msg) => {\\n    ptyProcess.resize(msg.w, msg.h);\\n  });\\n  ptyProcess.on('data', function(data) {\\n    socket.emit('_term_write_out', data);\\n  });\\n});\\n\\n// \\u5F00\\u542F server\\napp.get('/', (req, res) => {\\n  res.sendFile(__dirname + '/index.html');\\n});\\nhttp.listen(3000, () => {\\n  console.log('listening on *:3000');\\n});\\n\")), mdx(\"p\", null, \"client \\u7684\\u90E8\\u5206\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import io from 'socket.io-client';\\n\\n// \\u5F00\\u542F ws client\\uFF0Csocket.io \\u4E0D\\u9700\\u8981\\u5173\\u5FC3\\u91CD\\u8FDE\\u548C\\u590D\\u6742\\u6570\\u636E\\u7C7B\\u578B\\u7B49\\u5904\\u7406\\nconst socket = io('http://localhost');\\n\\n// \\u5F00\\u542F\\u7EC8\\u7AEF\\u7ED1\\u5B9A\\u5230\\u89C6\\u56FE\\nconst term = new Terminal();\\nterm.open(document.getElementById('terminal'));\\n\\n// \\u8FDE\\u63A5\\u7EC8\\u7AEF\\u548C ws \\u6570\\u636E\\u901A\\u9053\\nsocket.on('connect', () => {\\n  socket.on('_term_write_out', (msg) => {\\n    term.write(msg)\\n  });\\n  term.onData((data) => {\\n    socket.emit('data', data)\\n  })\\n});\\n\")), mdx(\"h3\", null, \"2. \\u7B2C\\u4E8C\\u7248 Docker\"), mdx(\"p\", null, \"node-pty \\u662F\\u5728\\u673A\\u5668\\u672C\\u8EAB\\u6267\\u884C\\u7684\\uFF0C\\u548C server \\u96C6\\u6210\\u5728\\u4E00\\u8D77\\uFF0C\\u4E0D\\u662F\\u7279\\u522B\\u5E72\\u51C0\\uFF0C\\u540E\\u6765\\u52A0\\u5165 docker \\u6280\\u672F\\u6808\\u7684\\u65F6\\u5019\\u5C31\\u6CA1\\u529E\\u6CD5\\u4F7F\\u7528\\u4E86\\uFF0C\\u9700\\u8981\\u5C06\\u7EC8\\u7AEF\\u670D\\u52A1\\u4ECE docker \\u4E2D\\u5F15\\u5165\\uFF0C\\u597D\\u5728 docker \\u672C\\u8EAB\\u53EF\\u4EE5\\u901A\\u8FC7 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"exec\"), \" \\u652F\\u6301\\u8FD9\\u4E2A\\u529F\\u80FD\\uFF1A\"), mdx(\"p\", null, \"\\u670D\\u52A1\\u7AEF\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"const container: Docker.Container = docker.getContainer(config.containerId);\\n\\n// \\u5224\\u65AD docker \\u5BB9\\u5668\\u72B6\\u6001\\u662F\\u5426\\u8FD0\\u884C\\nconst ContainerInfo = await container.inspect();\\nif (!ContainerInfo.State.Running) {\\n  ctx.socket.emit(\\\"error\\\", ContainerInfo.State.Status);\\n}\\n\\n// \\u5B9A\\u4E49\\u7EC8\\u7AEF\\u914D\\u7F6E\\nconst cmd = {\\n  AttachStdout: true,\\n  AttachStderr: true,\\n  AttachStdin: true,\\n  Tty: true,\\n  WorkingDir: workdir || \\\"/workspace\\\",\\n  Cmd: [\\\"zsh\\\"]\\n};\\n\\n// \\u5728\\u5BB9\\u5668\\u4E0A\\u8FD0\\u884C\\u7EC8\\u7AEF\\ncontainer.exec(cmd, (err, exec) => {\\n  // \\u76D1\\u542C\\u5BB9\\u5668\\n  container.wait((_, __) => {\\n    ctx.socket.emit(\\\"end\\\", \\\"ended\\\");\\n  });\\n\\n  if (err) {\\n    return;\\n  }\\n\\n  // \\u6267\\u884C\\u914D\\u7F6E\\n  const options = {\\n    Tty: true,\\n    Detach: false,\\n    stream: true,\\n    stdin: true,\\n    stdout: true,\\n    stderr: true,\\n    hijack: true // fix vim\\n  };\\n\\n  // \\u542F\\u52A8\\u4E00\\u4E2A\\u8FDB\\u7A0B\\u6765\\u8FD0\\u884C\\uFF0C\\u62FF\\u5230 stream \\u6570\\u636E\\u6D41\\u6765\\u548C\\u5BA2\\u6237\\u7AEF\\u4EA4\\u4E92\\n  exec.start(options, (_: any, stream: NodeJS.WritableStream) => {\\n\\n    // \\u521D\\u59CB\\u5316\\u8F93\\u5165\\u8F93\\u51FA\\u7684\\u5C3A\\u5BF8\\n    const dimensions = {\\n      h: parseInt(ctx.socket.handshake.query.rows),\\n      w: parseInt(ctx.socket.handshake.query.cols)\\n    };\\n    if (dimensions.h != 0 && dimensions.w != 0) {\\n      exec.resize(dimensions, () => {});\\n    }\\n\\n    // \\u76D1\\u542C\\u5BA2\\u6237\\u7AEF\\u7684\\u8F93\\u5165\\uFF0C\\u53D1\\u9001\\u5230 exec \\u7684 steam\\n    ctx.socket.on(\\\"data\\\", data => stream.write(data));\\n    // \\u76D1\\u542C\\u5BA2\\u6237\\u7AEF\\u7684\\u8F93\\u5165\\uFF0C\\u53D1\\u9001\\u5230 exec \\u7684 steam\\n    ctx.socket.on(\\\"resize\\\", dimensions =>\\n      exec.resize(dimensions, () => {})\\n    );\\n    ctx.socket.on(\\\"exit\\\", _ => exiter());\\n\\n    // \\u76D1\\u542C exec \\u7684\\u8F93\\u51FA\\uFF0C\\u53D1\\u9001\\u5230\\u5BA2\\u6237\\u7AEF\\n    stream.on(\\\"data\\\", chunk => ctx.socket.emit(\\\"data\\\", chunk.toString()));\\n    // \\u76D1\\u542C exec \\u7684\\u9519\\u8BEF\\n    stream.on(\\\"error\\\", data => ctx.socket.emit(\\\"error\\\", data));\\n    // \\u76D1\\u542C exec \\u7684\\u7ED3\\u675F\\n    stream.on(\\\"end\\\", data => ctx.socket.emit(\\\"exit\\\", data));\\n  });\\n});\\n\")), mdx(\"p\", null, \"\\u5BA2\\u6237\\u7AEF\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u8FDE\\u63A5\\u670D\\u52A1\\u7AEF\\nthis.socket = io('ws://127.0.0.1:7001/term', connectOpts);\\n\\n// \\u6570\\u636E\\u76D1\\u542C\\nthis.socket.on('connect', () => {\\n  this.updateSize();\\n  this.setState({connectStatus: 1});\\n});\\nthis.socket.on('connected', () => {\\n  this.updateSize();\\n  this.triggerListeners('socket-connected');\\n});\\nthis.socket.on('disconnect', () => {\\n  this.setState({ connectStatus: 2 });\\n  this.triggerListeners('socket-disconnect');\\n})\\nthis.socket.on('exit', () => {\\n  this.disconnect();\\n  this.triggerListeners('socket-exit');\\n})\\nthis.socket.on('error', () => {})\\n\\n// \\u670D\\u52A1\\u7AEF\\u8F93\\u51FA\\u5230 xterm\\nthis.socket.on('data', (data: any) => {\\n  this.ondownStream();\\n  this.xterm.write(data)\\n  this.triggerListeners('socket-data', { data });\\n})\\n\\n// \\u6570\\u636E\\u548C\\u72B6\\u6001\\u76D1\\u542C\\nthis.xterm.onTitleChange((title) => {\\n  this.setState({ title })\\n});\\nthis.xterm.onData((data) => {\\n  this.updateSize();\\n  this.onupStream();\\n  this.socket.emit('data', data)\\n  this.triggerListeners('xterm-data', { data });\\n})\\nthis.xterm.onResize(() => {\\n  this.setState({dims: `${this.xterm.cols}\\xD7${this.xterm.rows}`})\\n})\\nthis.xterm.onCursorMove(() => {\\n  this.setState({cursor: `${this.xterm.buffer.cursorX}\\xD7${this.xterm.buffer.cursorY}`})\\n})\\nthis.xterm.focus();\\nthis.updateSize();\\n\")), mdx(\"p\", null, \"\\u52A0\\u4E0A\\u4E00\\u4E9B\\u8FB9\\u754C\\u548C\\u89C6\\u56FE\\u7684\\u6837\\u5F0F\\uFF0C\\u5C31\\u80FD\\u5B9E\\u73B0\\u6700\\u5F00\\u59CB\\u89C6\\u9891\\u6F14\\u793A\\u7684\\u6548\\u679C\\u4E86~\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"850px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/f1dea28d9203221ceb1f1c914a826ca1/8820e/term-peek.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"30.888030888030887%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAAAoUlEQVQY053Oyw6CMBAF0AIixEegJYVCARUamkJExf//tmvjig1EWZzMIzOTIY/3C2aaoPsBvVLomwbjfYAxBm3bQtner7TWIJXpIMYnStVBRhRpeIAQAr6/ByHkf0F0hEcZTjRBHIQ4ex4SRuG67raDO3tgecCZxQXOzLfe8sUaIWvk5RVZUSHNS5tfwLhAxLiVruCIkwyyvqGwhN3lQuIDpJyIy61Lav0AAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"终端的集成\",\n    \"title\": \"终端的集成\",\n    \"src\": \"/static/f1dea28d9203221ceb1f1c914a826ca1/8820e/term-peek.png\",\n    \"srcSet\": [\"/static/f1dea28d9203221ceb1f1c914a826ca1/ae269/term-peek.png 259w\", \"/static/f1dea28d9203221ceb1f1c914a826ca1/a4dff/term-peek.png 518w\", \"/static/f1dea28d9203221ceb1f1c914a826ca1/8820e/term-peek.png 850w\"],\n    \"sizes\": \"(max-width: 850px) 100vw, 850px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u7EC8\\u7AEF\\u7684\\u96C6\\u6210\"), \"\\n  \")), mdx(\"div\", {\n    \"style\": {},\n    \"'flex',\": \"\",\n    \"justifycontent:\": \"\",\n    \"'center'}}\": \"\"\n  }, \"\\n  \", mdx(\"figure\", {\n    parentName: \"div\",\n    \"className\": \"gatsby-resp-image-figure\"\n  }, \"\\n    \", mdx(\"img\", {\n    parentName: \"figure\",\n    \"src\": \"/term-stru-e94eacefae1ad9d76eb318564ecd68e4.svg\"\n  }), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u7EC8\\u7AEF\\u80FD\\u529B\\u67B6\\u6784\"), \"\\n  \")), mdx(\"h2\", null, \"\\u56DB\\u3001docker \\u8FDB\\u7A0B\\u56DE\\u6536\\u95EE\\u9898\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"958px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"27.413127413127413%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsSAAALEgHS3X78AAABH0lEQVQY0z2QTWvCUBBFH34sXIuIkqoJCi6qlSQSmiaxAUHFxBgDSSDtquD//wenmQft4jLz5g2Xe0bZto3v+0jdbDbsdjvde56H67o4jqO1XC61VqsVpmkSxzHX65UgCEiSlPP5zPF4RG23W6bTqV42DIPZbKb7v9l8Pme9XjOZTOh0OiiltBzH5vl8cjqdSNOUoijIsgyVJAn3+52qqsjznKZpqOuay+WiE8hM3o/HA9mVeRCGeP4Hzdc3n4eDNhIPkTJNS2NIEkkkmIK93+91lXRRFBG2JqPRiMFgQL/XI3Hf+KlLguhA3hqVZcntdkMZxovGGQ6HjMfjf3PLslgsFvpPbiun6Ha79Pp9ui1y5bxSxCHvQUjWGgmyEP0CZgygr+cz4mUAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"终端与容器进程的对应\",\n    \"title\": \"终端与容器进程的对应\",\n    \"src\": \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png\",\n    \"srcSet\": [\"/static/e425ecabd045bc5c9d0fd4e844fac542/ae269/term-process.png 259w\", \"/static/e425ecabd045bc5c9d0fd4e844fac542/a4dff/term-process.png 518w\", \"/static/e425ecabd045bc5c9d0fd4e844fac542/37bc7/term-process.png 958w\"],\n    \"sizes\": \"(max-width: 958px) 100vw, 958px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u7EC8\\u7AEF\\u4E0E\\u5BB9\\u5668\\u8FDB\\u7A0B\\u7684\\u5BF9\\u5E94\"), \"\\n  \")), mdx(\"p\", null, \"\\u5728\\u96C6\\u6210 docker \\u7684\\u65F6\\u5019\\uFF0C\\u51FA\\u73B0\\u4E00\\u4E2A\\u95EE\\u9898\\u5C31\\u662F\\u5BA2\\u6237\\u7AEF\\u5237\\u65B0\\u591A\\u6B21\\u4E4B\\u540E\\uFF0C\\u670D\\u52A1\\u7AEF\\u51FA\\u73B0\\u5F88\\u591A\\u8FDE\\u63A5\\u8FDB\\u7A0B\\u6CA1\\u529E\\u6CD5\\u81EA\\u52A8\\u4E2D\\u65AD\\u3002\\u7B80\\u5355\\u641C\\u7D22\\u4E4B\\u540E\\u53D1\\u73B0\\u56E0\\u4E3A Terminal \\u5728 Container \\u91CC\\u542F\\u52A8\\u4E86 zsh\\uFF0C\\u800C zsh \\u53EF\\u4EE5\\u968F\\u610F\\u6267\\u884C\\u547D\\u4EE4\\u542F\\u52A8\\u8FDB\\u7A0B\\uFF0C\\u50F5\\u5C38\\u8FDB\\u7A0B\\u95EE\\u9898\\u5F88\\u96BE\\u907F\\u514D\\u3002\"), mdx(\"p\", null, \"\\u4E0D\\u8FC7\\u53EF\\u4EE5\\u4F7F\\u7528 phusion/baseimage \\u955C\\u50CF\\u6765\\u89E3\\u51B3\\u8FD9\\u4E2A\\u95EE\\u9898\\uFF0C\\u53EF\\u4EE5\\u67E5\\u770B \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/phusion/baseimage-docker\"\n  }, \"\\u5B98\\u65B9\\u6587\\u6863\"), \"\\u3002\"));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"isCreatedByStatefulCreatePages":false,"id":"9f8935ba-d981-525a-b4fe-5a48a8c00e99","prev":{"fileAbsolutePath":"E:/u-codes/storybok/content/blog/workpad/workpad-part-5.md","id":"375813ee-f566-5c96-960c-56022600d585","parent":{"name":"workpad-part-5","sourceInstanceName":"blog"},"excerpt":"一、为什么要用 textmate 而不是内置的？ 实现 IDE 的过程中好奇为什么 moanco-editor 和 vscode 的高亮不太一样，比较简陋很不舒服，一番搜索发现  monaco-editor  的语言支持使用的是内置的  Monarch  这个语法高亮支持。 官方的解释  Why doesn't the editor support TextMate grammars? ： 主要就是因为  Textmate  语法解析依赖的  Oniguruma  是一个 C…","fields":{"title":"🌋 WebIDE 的开发记录其五（monaco-editor + textmate）","slug":"/blog/workpad-part-5","description":"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第五篇文章，谈谈怎么在 monaco-editor 用 textmate 替换内置语法和高亮的。","date":"2020-01-27","redirects":null,"datetime":"2020-01-27 20:03:43","categories":["webide"],"series":"WebIDE 的开发记录","tags":["思考","整理","WorkPad","WebIDE","云开发","在线编辑器"],"status":"online"},"frontmatter":{"published":null,"tags":["思考","整理","WorkPad","WebIDE","云开发","在线编辑器"],"theme":null,"slug":"workpad-part-5","date":"2020-01-27 20:03:43"},"body":"const _excluded = [\"components\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }\n/* @jsx mdx */\n\nconst _frontmatter = {\n  \"slug\": \"workpad-part-5\",\n  \"title\": \"🌋 WebIDE 的开发记录其五（monaco-editor + textmate）\",\n  \"date\": \"2020-01-27 20:03:43\",\n  \"author\": \"Ubug\",\n  \"description\": \"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第五篇文章，谈谈怎么在 monaco-editor 用 textmate 替换内置语法和高亮的。\",\n  \"series\": \"WebIDE 的开发记录\",\n  \"categories\": [\"webide\"],\n  \"tags\": [\"思考\", \"整理\", \"WorkPad\", \"WebIDE\", \"云开发\", \"在线编辑器\"],\n  \"banner\": \"./WorkPad-demo.png\"\n};\nconst makeShortcode = name => function MDXDefaultShortcode(props) {\n  console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n  return mdx(\"div\", props);\n};\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n      components\n    } = _ref,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h2\", null, \"\\u4E00\\u3001\\u4E3A\\u4EC0\\u4E48\\u8981\\u7528 textmate \\u800C\\u4E0D\\u662F\\u5185\\u7F6E\\u7684\\uFF1F\"), mdx(\"p\", null, \"\\u5B9E\\u73B0 IDE \\u7684\\u8FC7\\u7A0B\\u4E2D\\u597D\\u5947\\u4E3A\\u4EC0\\u4E48 moanco-editor \\u548C vscode \\u7684\\u9AD8\\u4EAE\\u4E0D\\u592A\\u4E00\\u6837\\uFF0C\\u6BD4\\u8F83\\u7B80\\u964B\\u5F88\\u4E0D\\u8212\\u670D\\uFF0C\\u4E00\\u756A\\u641C\\u7D22\\u53D1\\u73B0 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"monaco-editor\"), \" \\u7684\\u8BED\\u8A00\\u652F\\u6301\\u4F7F\\u7528\\u7684\\u662F\\u5185\\u7F6E\\u7684 \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://microsoft.github.io/monaco-editor/monarch.html\"\n  }, \"Monarch\"), \" \\u8FD9\\u4E2A\\u8BED\\u6CD5\\u9AD8\\u4EAE\\u652F\\u6301\\u3002\"), mdx(\"p\", null, \"\\u5B98\\u65B9\\u7684\\u89E3\\u91CA \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/Microsoft/monaco-editor#faq\"\n  }, \"Why doesn't the editor support TextMate grammars?\"), \"\\uFF1A\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"935px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/f9d27b60b893d7d96372e73e527a3c40/7fb2f/why-not-text-mate.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"34.36293436293437%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABJklEQVQoz01RAXKDIBD0/x9s2misgmBsmwgommjdsmecKTM3t3fAsrdkqmlgrYVOuWkMjLGolYbWDZTWcM5j+QWWdcOyLHgynk/BjHVd8X9lJCIByY5MsiYRG3nIorQ9avONqqpSbeQhOZMwz937Hr1zQp7xUttecb12ODBV3u53TNOEGCPmKWIcBsHTNGOeZ8EMH4LUVL1tG7KPc468uOBSljjnhQR7xaWUPvHRO+c5Tqd3vKXg+Z/bDV33hTERPx6PnVD8krEVVMLqGCVFVStRPSR1vDSMI0IY4H2QXoz7BKP0w05IMpJwTJJ8Jp+quhY/2devPfpGclpjbSvYtu3LRyMeyqew0fdOFNAfeiKKxiiZNV933osynzJVci+kcFIH8ZDrD+yCDyW5KWW5AAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"为什么 monaco 不用 textmate\",\n    \"title\": \"为什么 monaco 不用 textmate\",\n    \"src\": \"/static/f9d27b60b893d7d96372e73e527a3c40/7fb2f/why-not-text-mate.png\",\n    \"srcSet\": [\"/static/f9d27b60b893d7d96372e73e527a3c40/ae269/why-not-text-mate.png 259w\", \"/static/f9d27b60b893d7d96372e73e527a3c40/a4dff/why-not-text-mate.png 518w\", \"/static/f9d27b60b893d7d96372e73e527a3c40/7fb2f/why-not-text-mate.png 935w\"],\n    \"sizes\": \"(max-width: 935px) 100vw, 935px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u4E3A\\u4EC0\\u4E48 monaco \\u4E0D\\u7528 textmate\"), \"\\n  \")), mdx(\"p\", null, \"\\u4E3B\\u8981\\u5C31\\u662F\\u56E0\\u4E3A \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Textmate\"), \" \\u8BED\\u6CD5\\u89E3\\u6790\\u4F9D\\u8D56\\u7684 \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/kkos/oniguruma\"\n  }, \"Oniguruma\"), \" \\u662F\\u4E00\\u4E2A C \\u8BED\\u8A00\\u4E0B\\u7684\\u89E3\\u6790\\u529F\\u80FD\\uFF0CVSCode \\u53EF\\u4EE5\\u4F7F\\u7528 node \\u73AF\\u5883\\u6765\\u8C03\\u7528\\u539F\\u751F\\u7684\\u6A21\\u5757\\uFF0C\\u4F46\\u662F\\u5728 web \\u73AF\\u5883\\u4E0B\\u65E0\\u6CD5\\u5B9E\\u73B0\\uFF0C\\u5373\\u4F7F\\u901A\\u8FC7 asm.js \\u8F6C\\u6362\\u540E\\uFF0C\\u6027\\u80FD\\u4F9D\\u7136\\u4F1A\\u6709 100-1000 \\u500D\\u7684\\u635F\\u5931\\uFF0816\\u5E749\\u6708\\u7684\\u8BF4\\u660E\\uFF0C\\u76EE\\u524D\\u672A\\u6D4B\\u8BD5\\uFF09\\uFF0C\\u800C\\u4E14 IE \\u4E0D\\u652F\\u6301~~~\"), mdx(\"p\", null, \"\\u8BED\\u8A00\\u7684\\u652F\\u6301\\u4E5F\\u53EA\\u6709\\u901A\\u8FC7 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"worker\"), \" \\u7684 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"js\"), \" \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ts\"), \" \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"html\"), \" \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"css\"), \" \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"json\"), \" \\u8FD9\\u4E9B\\u3002\\u4F46\\u662F\\u4E1A\\u5185\\u66F4\\u901A\\u7528\\u3001\\u751F\\u6001\\u66F4\\u4E30\\u5BCC\\u7684\\u662F \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://macromates.com/manual/en/language_grammars\"\n  }, \"Textmate\"), \"\\uFF0C\\u5305\\u62EC \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"VSCode\"), \" \\u4E5F\\u662F\\u7528\\u7684 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Textmate\"), \"\\u3002\"), mdx(\"p\", null, \"\\u800C\\u5B98\\u65B9\\u8BF4\\u7684 asm.js \\u7684\\u65B9\\u5F0F\\u7684\\u7F3A\\u70B9\\uFF0C\\u6211\\u8BA4\\u4E3A\\u90FD\\u662F\\u53EF\\u4EE5\\u63A5\\u53D7\\u7684\\uFF0C\\u6240\\u4EE5\\u4ECD\\u7136\\u60F3\\u5C1D\\u8BD5\\u4F7F\\u7528 textmate\\u3002\"), mdx(\"h2\", null, \"\\u4E8C\\u3001\\u524D\\u4EBA\\u683D\\u6811\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"ps: \\u6700\\u8FD1 \", \"[Apr 16, 2020]\", \" vscode \\u5C06 oniguruma \\u4ECE\\u539F\\u751F\\u6A21\\u5757 \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/atom/node-oniguruma\"\n  }, \"node-oniguruma\"), \" \\u72EC\\u7ACB\\u51FA\\u6765\\u4E3A wasm \\u7248\\u672C\\u7684 \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/microsoft/vscode-oniguruma\"\n  }, \"vscode-oniguruma\"), \"\\uFF0C\\u4E4B\\u524D\\u7684\\u6587\\u5B57\\u505A\\u4E86\\u4E9B\\u4FEE\\u6539\\u3002\")), mdx(\"p\", null, \"\\u8003\\u8651\\u5230\\u80FD\\u7528\\u548C\\u6027\\u80FD\\uFF0C\\u5148\\u89E3\\u51B3\\u80FD\\u7528\\u95EE\\u9898\\uFF0C\\u8003\\u8651 asm.js \\u4E0B\\u7684\\u5B9E\\u73B0\\uFF08vscode-textmate \\u6D4B\\u8BD5\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/microsoft/vscode-textmate/blob/master/src/tests/onigLibs.ts\"\n  }, \"\\u4E09\\u79CD\\u83B7\\u53D6 OnigLib \\u7684\\u65B9\\u5F0F\"), \"\\u601D\\u8DEF\\u63D0\\u4F9B\\u4E86\\u5F88\\u5927\\u5E2E\\u52A9\\uFF09\\uFF1A\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"436px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/187692d88ac451443b3daa7835ae1fa9/7c30a/textmate-two-ways.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"16.602316602316602%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsSAAALEgHS3X78AAAApklEQVQI1zVPAQ6DIBDz/x90mYlTEBQBEUGY09EhyS5pLpdre70q7QHBWkitIYSAMQbOOSilMxTmWRaovI8xwnuPze3w4V2413XiXyklVJdZ4aVCRynq+oH21WFgDG37Ah/HgmfToCcEhFCQzBsnAbs5cM5hXcCSPW7zu6rvauGyIWW8CIoRHzHltPfMsqjrCSgdyqFlMWC5bz5CSF0++ZwnjuMoCX+UEeIJYOo2fwAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"vscode-textmate 中的 benchmark 测试三种方式\",\n    \"title\": \"vscode-textmate 中的 benchmark 测试三种方式\",\n    \"src\": \"/static/187692d88ac451443b3daa7835ae1fa9/7c30a/textmate-two-ways.png\",\n    \"srcSet\": [\"/static/187692d88ac451443b3daa7835ae1fa9/ae269/textmate-two-ways.png 259w\", \"/static/187692d88ac451443b3daa7835ae1fa9/7c30a/textmate-two-ways.png 436w\"],\n    \"sizes\": \"(max-width: 436px) 100vw, 436px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"vscode-textmate \\u4E2D\\u7684 benchmark \\u6D4B\\u8BD5\\u4E09\\u79CD\\u65B9\\u5F0F\"), \"\\n  \")), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"name\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"project\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"desc\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onigurumaLib\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"a\", {\n    parentName: \"td\",\n    \"href\": \"https://github.com/kkos/oniguruma\"\n  }, \"oniguruma\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u662F\\u7528 c \\u7684\\u4E00\\u4E2A\\u89E3\\u91CA\\u5668\\uFF0C\\u4E0D\\u662F node \\u6216\\u8005 \\u6D4F\\u89C8\\u5668\\u6A21\\u5757\\uFF0C\\u65E0\\u6CD5\\u5728\\u524D\\u7AEF\\u9879\\u76EE\\u4E2D\\u4F7F\\u7528\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"node-oniguruma]\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"a\", {\n    parentName: \"td\",\n    \"href\": \"https://github.com/atom/node-oniguruma\"\n  }, \"node-oniguruma\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"atom \\u5BF9 oniguruma \\u5C01\\u88C5\\u7684 node \\u6A21\\u5757\\uFF0C\\u65E0\\u6CD5\\u5728\\u6D4F\\u89C8\\u5668\\u7AEF\\u8FD0\\u884C\\u3002VSCode \\u4E4B\\u524D\\u4F7F\\u7528\\u7684\\u6A21\\u5757\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"vscode-oniguruma\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"a\", {\n    parentName: \"td\",\n    \"href\": \"https://github.com/microsoft/vscode-oniguruma\"\n  }, \"vscode-oniguruma\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"[\\u6700\\u8FD1\\u66F4\\u65B0]\"), \" vscode \\u7528 wasm \\u5BF9 oniguruma \\u5C01\\u88C5\\u7684\\u6A21\\u5757\\uFF0C\\u5E94\\u8BE5\\u53EF\\u4EE5\\u5728\\u6D4F\\u89C8\\u5668\\u7AEF\\u8FD0\\u884C\\uFF0C\\u4F46\\u662F\", \"[Apr 16, 2020]\", \"\\u521A\\u521B\\u5EFA\\u7684\\u9879\\u76EE\\u8FD8\\u6CA1\\u8BD5\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onigasm\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"a\", {\n    parentName: \"td\",\n    \"href\": \"https://github.com/NeekSandhu/onigasm\"\n  }, \"onigasm\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u4F7F\\u7528 WebAssembly \\u7684\\u6280\\u672F\\u5C06 c \\u7684\\u7248\\u672C\\u79FB\\u690D\\u5230 wasm\\uFF0C\\u8FD9\\u4E2A\\u662F\\u53EF\\u4EE5\\u5728 web \\u7AEF\\u8FD0\\u884C\\uFF08\\u56E0\\u4E3A\\u6CA1\\u6709 V8 \\u7684\\u4E00\\u4E9B\\u5B9A\\u5236\\u52A0\\u6210\\uFF0C\\u6027\\u80FD\\u6BD4 node-oniguruma \\u5DEE 2 \\u500D\\uFF0C\\u76F8\\u6BD4 C \\u4E0B\\u7684 oniguruma \\u672A\\u77E5\\uFF09\")))), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"vscode-textmate \\u4E0B\\u6709 benchmark \\u6D4B\\u8BD5\\u53EF\\u4EE5\\u770B\\u4E0B \\u539F\\u751F\\u4E0B\\u7684 oniguruma \\u548C asm \\u4E0B\\u7684 onigasm \\u6027\\u80FD\\u5DEE\\u5F02\")), mdx(\"p\", null, \"\\u73B0\\u5728\\u7684\\u601D\\u8DEF\\u5982\\u4E0B\\uFF1A\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u4F7F\\u7528 moanco-editor-core \\u4EE3\\u66FF monaco-editor \\u53BB\\u9664\\u81EA\\u5E26\\u7684\\u8BED\\u6CD5\\u652F\\u6301\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u4F7F\\u7528 \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NeekSandhu/onigasm\"\n  }, \"onigasm\"), \" \\u7684 WebAssembly \\u7684\\u6280\\u672F\\u5C06 c \\u7684\\u7248\\u672C\\u79FB\\u690D\\u5230 wasm\\uFF0C\\u4F5C\\u4E3A\\u89E3\\u91CA\\u5668\\u5728\\u524D\\u7AEF\\u5F15\\u5165\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u4F7F\\u7528 vscode-textmate \\u5E93\\u6765\\u52A0\\u8F7D\\u8BED\\u6CD5\\u89E3\\u91CA\\u5668\\uFF0C\\u8F6C\\u4E3A monaco-editor \\u652F\\u6301\\u7684\\u8BED\\u6CD5\\u4E3B\\u9898\\uFF0C\\u6B64\\u65F6\\u5373\\u53EF\\u5B9E\\u73B0 textmate \\u7684\\u8BED\\u6CD5\\u89E3\\u6790\\u4E86\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u81F3\\u6B64\\u9AD8\\u4EAE\\u4E3B\\u9898\\u5C31\\u5B9E\\u73B0\\u4E86 textmate \\u7684\\u66FF\\u4EE3\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u518D\\u4F7F\\u7528 vscode \\u91CC\\u9762\\u7684\\u4E3B\\u9898\\u6587\\u4EF6\\u8F6C\\u6362\\u4E0B\\u7ED9 monaco \\u4F7F\\u7528\\uFF0C\\u9AD8\\u4EAE\\u548C VScode \\u4FDD\\u6301\\u4E00\\u81F4\")), mdx(\"p\", null, \"\\u597D\\u50CF\\u5E76\\u4E0D\\u662F\\u5F88\\u590D\\u6742\\u7684\\u6837\\u5B50\\uFF0C\\u8BE5\\u6709\\u7684\\u5DE5\\u5177\\u90FD\\u63D0\\u4F9B\\u7ED9\\u4E86\\u6211\\u4EEC\\uFF0C\\u53EA\\u9700\\u8981\\u7C98\\u5728\\u4E00\\u8D77\\u5C31\\u884C\\uFF08\\u53EF\\u662F\\u597D\\u50CF\\u4E5F\\u5E76\\u6CA1\\u6709\\u8FD9\\u4E48\\u7B80\\u5355\\uFF09~\"), mdx(\"h2\", null, \"\\u4E09\\u3001\\u4E00\\u4E9B\\u6982\\u5FF5\\u548C\\u6D41\\u7A0B\"), mdx(\"p\", null, \"\\u96C6\\u6210\\u7684\\u8FC7\\u7A0B\\u6709\\u4E9B\\u590D\\u6742\\uFF0C\\u6D89\\u53CA\\u5230\\u5F88\\u591A\\u7684\\u5C01\\u88C5\\u548C\\u6982\\u5FF5\\uFF0C\\u5F53\\u65F6\\u505A\\u7684\\u65F6\\u5019\\u8E29\\u4E86\\u5F88\\u591A\\u5751\\uFF0C\\u8FD9\\u91CC\\u4E5F\\u4E0D\\u53EF\\u80FD\\u592A\\u8BE6\\u5C3D\\uFF0C\\u51D1\\u6D3B\\u770B\\uFF0C\\u60F3\\u8981\\u770B\\u66F4\\u8BE6\\u5C3D\\u7684\\u53EF\\u4EE5\\u5230 theia \\u9879\\u76EE\\u4E2D\\u770B\\u76F8\\u5173\\u4EE3\\u7801\\uFF1A\"), mdx(\"h3\", null, \"1. \\u6D41\\u7A0B\\u7B80\\u8FF0\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"monaco-editor \\u63A5\\u53D7\\u4E00\\u4E2A\\u4E3B\\u9898\\uFF0C\\u6765\\u8D1F\\u8D23\\u5BF9\\u5143\\u7D20\\u7740\\u8272\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"monaco-editor \\u63A5\\u53D7\\u4E00\\u4E2A\\u8BED\\u8A00\\u89E3\\u6790\\u5668\\uFF0C\\u6765\\u51B3\\u5B9A\\u4EE3\\u7801\\u4E2D\\u7684\\u67D0\\u4E00\\u6BB5\\u662F\\u4EC0\\u4E48\\u5143\\u7D20\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"textmate \\u63D0\\u4F9B\\u8BED\\u8A00\\u7684\\u8BED\\u6CD5\\u914D\\u7F6E\\uFF0C\\u518D\\u52A0\\u4E0A\\u4E00\\u4E9B monaco-editor \\u7684\\u8BED\\u8A00\\u652F\\u6301\\uFF0C\\u751F\\u6210 grammarProvider\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"textmate \\u6CE8\\u518C TextmateRegistry\\uFF0C\\u7136\\u540E\\u6302\\u8F7D\\u4E0D\\u540C\\u8BED\\u8A00\\u7684 grammarProvider \\u4FDD\\u5B58\\u89E3\\u6790\\u914D\\u7F6E\\u4E4B\\u7C7B\\u7684\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u4F7F\\u7528 onigasm \\u6CE8\\u518C\\u8BED\\u6CD5\\u89E3\\u6790\\u5668 grammarRegistry\\uFF0C\\u7136\\u540E\\u521B\\u5EFA\\u4E0D\\u540C\\u8BED\\u8A00\\u5B9E\\u9645\\u7684\\u89E3\\u6790\\u5668 TextmateTokenizer\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"monaco \\u7684 monaco.languages.setTokensProvider \\u4F7F\\u7528 TextmateTokenizer \\u89E3\\u6790\\u4E0D\\u540C\\u8BED\\u8A00\\u8BED\\u6CD5\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u5B8C\\u6210\\u6574\\u4E2A\\u8BED\\u6CD5\\u89E3\\u6790\\u7684\\u4EFB\\u52A1\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"vscode \\u7684\\u9AD8\\u4EAE\\u989C\\u8272\\u4E4B\\u7C7B\\u7684\\u8F6C\\u6362\\u4E00\\u4E0B\\u80FD\\u88AB monaco-editor \\u76F4\\u63A5\\u4F7F\\u7528\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"\\u8BED\\u6CD5\\u89E3\\u6790 + \\u8BED\\u6CD5\\u9AD8\\u4EAE\\u5B8C\\u6210\")), mdx(\"p\", null, \"\\u6D41\\u7A0B\\u6BD4\\u8F83\\u7B80\\u5355\\uFF0C\\u4F46\\u662F\\u5176\\u4E2D\\u6D89\\u53CA\\u7684\\u903B\\u8F91\\u8FD8\\u662F\\u6BD4\\u8F83\\u591A\\u7684\\uFF0C\\u4EC5\\u4EC5 grammarProvider \\u5C31\\u6D89\\u53CA\\u5230\\u6BCF\\u4E2A\\u8BED\\u8A00\\u7684\\u6CE8\\u518C\\u548C\\u5B9E\\u73B0\\uFF0CTextmateRegistry \\u4E5F\\u6709\\u5F88\\u591A\\u7684\\u58F0\\u660E\\u83B7\\u53D6\\u3001\\u914D\\u7F6E\\u8BFB\\u53D6\\u3001\\u89E3\\u6790\\u7B49\\u6D41\\u7A0B\\u3002\"), mdx(\"h3\", null, \"2. \\u6A21\\u5757\\u5212\\u5206\"), mdx(\"p\", null, \"\\u9879\\u76EE\\u4E2D\\u8FDB\\u884C\\u7684\\u5212\\u5206\\uFF0C\\u4E0D\\u662F\\u5FC5\\u987B\\u7684\\uFF1A\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"name\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"desc\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onigasm\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u7528\\u6765\\u63D0\\u4F9B textmate \\u89E3\\u6790\\u5185\\u6838 onig \\u7684\\u52A0\\u8F7D\\u548C\\u5F15\\u7528\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"vscode-textmate\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u7528\\u6765\\u63D0\\u4F9B\\u8BED\\u6CD5\\u89E3\\u6790\\u3001\\u8BED\\u6CD5\\u6CE8\\u518C\\u5668\\u3001\\u4E3B\\u9898\\u6CE8\\u518C\\u5668\\u7B49\\uFF0Cvscode \\u5B9E\\u73B0\\u7684 textmate \\u76F8\\u5173\\u6838\\u5FC3\\u529F\\u80FD\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"textmate-registry\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u7528\\u6765\\u63D0\\u4F9B\\u4E0D\\u540C\\u8BED\\u8A00\\u7684\\u52A0\\u8F7D\\u3001\\u914D\\u7F6E\\u3001\\u6CE8\\u518C\\u529F\\u80FD\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"languages\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u4E0D\\u540C\\u8BED\\u8A00\\u7684\\u5177\\u4F53\\u89E3\\u6790\\u529F\\u80FD\\u3001\\u914D\\u7F6E\\u548C\\u8BED\\u6CD5\\u8BBE\\u7F6E\\u7B49\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"textmate-tokenizer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u5C01\\u88C5\\u8BCD\\u6CD5\\u5206\\u6790\\u7684\\u63A5\\u53E3\\uFF0C\\u8BA9 monaco \\u80FD\\u591F\\u4F7F\\u7528 textmate \\u7684\\u89E3\\u6790\\u5668\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"theme-registry\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"\\u63D0\\u4F9B\\u4E3B\\u9898\\u7684\\u8F6C\\u6362\\u3001\\u52A0\\u8F7D\\u3001\\u7BA1\\u7406\\u3001\\u5207\\u6362\")))), mdx(\"h2\", null, \"\\u56DB\\u3001 \\u96C6\\u6210\"), mdx(\"h3\", null, \"1. \\u5148\\u5B9A\\u4E49\\u8BED\\u6CD5\\u6587\\u4EF6\"), mdx(\"p\", null, \"\\u5148\\u627E\\u627E html.tmLanguage.json \\u7C7B\\u4F3C\\u7684 textmate \\u8BED\\u6CD5\\u6587\\u4EF6\\uFF0C\\u8FD9\\u4E2A\\u6BD4\\u8F83\\u91CD\\u8981\\uFF0C\\u662F\\u8BED\\u6CD5\\u89E3\\u6790\\u7684\\u914D\\u7F6E\\u6587\\u4EF6\\u3002\\u4E00\\u822C\\u53EF\\u4EE5\\u5728 \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/textmate/html.tmbundle\"\n  }, \"https://github.com/textmate/html.tmbundle\"), \" \\u7C7B\\u4F3C\\u7684\\u5730\\u5740\\u4E2D\\u62FF\\u5230\\u3002\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"html.tmLanguage.json\"), \" \\u8FD9\\u4E2A\\u6587\\u4EF6\\u6CA1\\u529E\\u6CD5\\u76F4\\u63A5\\u4F7F\\u7528\\uFF0C\\u9700\\u8981\\u901A\\u8FC7 vscode-textmate \\u518D\\u8FDB\\u884C\\u8F6C\\u6362\\u624D\\u80FD\\u7ED9 monaco-editor \\u4F7F\\u7528\\u3002\"), mdx(\"p\", null, \"\\u800C\\u4E14\\u4EC5\\u6709\\u8FD9\\u4E2A\\u6587\\u4EF6\\u8FD8\\u4E0D\\u591F\\uFF0C\\u8FD8\\u9700\\u8981\\u9488\\u5BF9 monaco-editor \\u518D\\u8BBE\\u7F6E\\u4E00\\u4E9B\\u989D\\u5916\\u7684\\u52A8\\u4F5C\\uFF0C\\u6BD4\\u5982 \\u8BED\\u8A00\\u540E\\u7F00\\u3001\\u81EA\\u52A8\\u5173\\u95ED\\u3001\\u6298\\u53E0\\u7B49\\u903B\\u8F91\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u8BED\\u6CD5\\u652F\\u6301\\u7684\\u7EDF\\u4E00\\u63A5\\u53E3\\nexport interface LanguageGrammarDefinitionContribution {\\n  registerTextmateLanguage(registry: TextmateRegistry): void;\\n}\\nexport interface GrammarDefinition {\\n  format: 'json' | 'plist';\\n  content: object | string;\\n  location?: string;\\n}\\n\")), mdx(\"p\", null, \"\\u7136\\u540E\\u662F\\u5177\\u4F53\\u5B9E\\u73B0\\uFF0C\\u66F4\\u591A\\u7684\\u5B9E\\u73B0\\u53EF\\u4EE5\\u5728 Theia \\u9879\\u76EE\\u4E2D\\u627E\\u5230\\uFF0C\\u8FD9\\u91CC\\u6709\\u4E00\\u4E9B\\u6574\\u7406\\u548C\\u62BD\\u8C61\\u3002\\u56E0\\u4E3A\\u5177\\u4F53\\u6BCF\\u4E2A\\u8BED\\u8A00\\u7684\\u5B9E\\u73B0\\u6CA1\\u529E\\u6CD5\\u82B1\\u7CBE\\u529B\\u53BB\\u505A\\uFF0C\\u5F88\\u4E0D\\u73B0\\u5B9E\\uFF0C\\u76F4\\u63A5\\u62FF\\u6765\\u7528\\u4E86\\uFF08EPL v2 \\u5F00\\u6E90\\u8BC1\\u4E66\\uFF0C\\u7528\\u7684\\u8BDD\\u9700\\u8981\\u6CE8\\u610F\\uFF09\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { LanguageGrammarDefinitionContribution, GrammarDefinition } from '../';\\nimport { TextmateRegistry } from '@extension/Writer/textmate/textmate-registry';\\n\\nconst EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];\\n\\nexport class HtmlContribution implements LanguageGrammarDefinitionContribution {\\n\\n  readonly id = 'html';\\n  readonly scopeName = 'text.html.basic';\\n\\n  registerTextmateLanguage(registry: TextmateRegistry): void {\\n    monaco.languages.register({\\n      id: this.id,\\n      extensions: ['.html', '.htm', '.shtml', '.xhtml', '.mdoc', '.jsp', '.asp', '.aspx', '.jshtm'],\\n      aliases: ['HTML', 'htm', 'html', 'xhtml'],\\n      mimetypes: ['text/html', 'text/x-jshtm', 'text/template', 'text/ng-template'],\\n    });\\n    monaco.languages.setLanguageConfiguration(this.id, {\\n      wordPattern: /(-?\\\\d*\\\\.\\\\d\\\\w*)|([^\\\\`\\\\~\\\\!\\\\@\\\\$\\\\^\\\\&\\\\*\\\\(\\\\)\\\\=\\\\+\\\\[\\\\{\\\\]\\\\}\\\\\\\\\\\\|\\\\;\\\\:\\\\'\\\\\\\"\\\\,\\\\.\\\\<\\\\>\\\\/\\\\s]+)/g,\\n\\n      comments: {\\n        blockComment: ['<!--', '-->']\\n      },\\n\\n      brackets: [\\n        ['<!--', '-->'],\\n        ['<', '>'],\\n        ['{', '}'],\\n        ['(', ')']\\n      ],\\n\\n      autoClosingPairs: [\\n        { open: '{', close: '}' },\\n        { open: '[', close: ']' },\\n        { open: '(', close: ')' },\\n        { open: '\\\"', close: '\\\"' },\\n        { open: '\\\\'', close: '\\\\'' }\\n      ],\\n\\n      surroundingPairs: [\\n        { open: '\\\"', close: '\\\"' },\\n        { open: '\\\\'', close: '\\\\'' },\\n        { open: '{', close: '}' },\\n        { open: '[', close: ']' },\\n        { open: '(', close: ')' },\\n        { open: '<', close: '>' },\\n      ],\\n\\n      onEnterRules: [\\n        {\\n          beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\\\\\\\w][_:\\\\\\\\w-.\\\\\\\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),\\n          afterText: /^<\\\\/([_:\\\\w][_:\\\\w-.\\\\d]*)\\\\s*>$/i,\\n          action: { indentAction: monaco.languages.IndentAction.IndentOutdent }\\n        },\\n        {\\n          beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\\\\\\\w[\\\\\\\\w\\\\\\\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),\\n          action: { indentAction: monaco.languages.IndentAction.Indent }\\n        }\\n      ],\\n\\n      folding: {\\n        markers: {\\n          start: new RegExp('^\\\\\\\\s*<!--\\\\\\\\s*#region\\\\\\\\b.*-->'),\\n          end: new RegExp('^\\\\\\\\s*<!--\\\\\\\\s*#endregion\\\\\\\\b.*-->')\\n        }\\n      }\\n    });\\n\\n    const grammar = require('../data/html.tmLanguage.json');\\n    registry.registerTextmateGrammarScope(this.scopeName, {\\n      async getGrammarDefinition(): Promise<GrammarDefinition> {\\n        return {\\n          format: 'json',\\n          content: grammar\\n        };\\n      }\\n    });\\n    registry.mapLanguageIdToTextmateGrammar(this.id, this.scopeName);\\n  }\\n}\\n\")), mdx(\"p\", null, \"\\u6709\\u4E00\\u4E9B\\u56E0\\u4E3A\\u7BC7\\u5E45\\u95EE\\u9898\\u6CA1\\u6709\\u5199\\u5728\\u8FD9\\uFF0C\\u5176\\u4ED6\\u8BED\\u8A00\\u7684\\u914D\\u7F6E\\u4E5F\\u662F\\u7C7B\\u4F3C\\u7684\\uFF0C\\u751A\\u81F3\\u66F4\\u52A0\\u590D\\u6742\\uFF0C\\u6211\\u9879\\u76EE\\u4E2D\\u5F15\\u7528\\u4E86 41 \\u4E2A\\u8BED\\u8A00\\u914D\\u7F6E\\u6587\\u4EF6\\u3002\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u8FD9\\u91CC\\u5BFC\\u51FA\\u5B9E\\u4F8B\\u63D0\\u4F9B\\u7ED9 textmate \\u4F7F\\u7528\\nexport const languageContributions = [\\n  new HtmlContribution(),\\n  // ......\\n]\\n\")), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"PS: \\u8FD9\\u4E9B\\u903B\\u8F91\\u5728 theia \\u7684\\u9879\\u76EE\\u4E2D\\u627E\\u5230\\u7684\\uFF0C\\u8FD9\\u91CC\\u6709\\u62BD\\u8C61\\u6574\\u5408\\u4E4B\\u7C7B\\u7684\\u4E0D\\u53E6\\u8BF4\\u4E86~~\")), mdx(\"h3\", null, \"2. \\u521D\\u59CB\\u5316 textmate \\u80FD\\u529B\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u5982\\u679C\\u4E0D\\u652F\\u6301 WebAssembly\\uFF0C\\u90A3\\u4E48\\u4EC0\\u4E48\\u90FD\\u6CA1\\u6709\\u4E86\\nif (typeof (window as any).WebAssembly === 'undefined') {\\n  logger.error('Textmate support deactivated because WebAssembly is not detected.')\\n  throw Error();\\n}\\n\\n// \\u521D\\u59CB\\u5316\\u4E00\\u4E2A textmate \\u6CE8\\u518C\\u5668\\uFF0C\\u5404\\u4E2A\\u8BED\\u8A00\\u6302\\u8F7D\\u7528\\nconst textmateRegistry = new TextmateRegistry();\\n\\n// \\u5C06\\u5168\\u90E8\\u8BED\\u8A00\\u914D\\u7F6E\\u6CE8\\u518C\\u5230 textmate \\u4E2D\\uFF0C\\u4F46\\u662F\\u8FD8\\u4E0D\\u80FD\\u76F4\\u63A5\\u4F7F\\u7528\\nfor (const grammarProvider of languageContributions) {\\n  try {\\n    grammarProvider.registerTextmateLanguage(textmateRegistry);\\n  } catch (err) {\\n    console.error(err);\\n  }\\n}\\n\\n// onigasm \\u52A0\\u8F7D\\u8FC7\\u6765\\nconst onigasmPromise = fetchOnigasm().then(async buffer => {\\n  await loadWASM(buffer);\\n  return new OnigasmLib();\\n});\\n\\n\\n// \\u521D\\u59CB\\u5316\\u4E00\\u4E2A\\u6CE8\\u518C\\u5668\\uFF0C\\u6574\\u4E2A\\u8BED\\u6CD5\\u652F\\u6301\\u7684\\u6838\\u5FC3\\u3002\\u5305\\u542B\\u4E86 \\u4E3B\\u9898\\u3001\\u8BED\\u6CD5\\u52A0\\u8F7D\\u3001\\u8BED\\u6CD5\\u6CE8\\u5165\\u4E4B\\u7C7B\\u7684\\u529F\\u80FD\\ngrammarRegistry = new Registry({\\n  getOnigLib: () => onigasmPromise,\\n  theme: monacoThemeRegistry.getTheme(currentEditorTheme),\\n  loadGrammar: async (scopeName: string) => {\\n    const provider = textmateRegistry.getProvider(scopeName);\\n    if (provider) {\\n      const definition = await provider.getGrammarDefinition();\\n      let rawGrammar: IRawGrammar;\\n      if (typeof definition.content === 'string') {\\n        rawGrammar = parseRawGrammar(definition.content, definition.format === 'json' ? 'grammar.json' : 'grammar.plist');\\n      } else {\\n        rawGrammar = definition.content as IRawGrammar;\\n      }\\n      return rawGrammar;\\n    }\\n    return undefined;\\n  },\\n  getInjections: (scopeName: string) => {\\n    const provider = textmateRegistry.getProvider(scopeName);\\n    if (provider && provider.getInjections) {\\n      return provider.getInjections(scopeName);\\n    }\\n    return [];\\n  }\\n});\\n\\n// --------- \\u4E0B\\u9762\\u662F onigasm \\u7684\\u52A0\\u8F7D\\n\\n// onigasm \\u7684\\u63A5\\u53E3\\u5B9E\\u73B0\\nfunction fetchOnigasm(): Promise<ArrayBuffer> {\\n  return new Promise((resolve, reject) => {\\n    const onigasmPath = require('onigasm/lib/onigasm.wasm'); // webpack doing its magic here\\n    const request = new XMLHttpRequest();\\n\\n    request.onreadystatechange = function (): void {\\n      if (this.readyState === XMLHttpRequest.DONE) {\\n        if (this.status === 200) {\\n          logger.log('\\u8BED\\u6CD5\\u9AD8\\u4EAE\\u5206\\u6790\\u6A21\\u5757 onigasm \\u4E0B\\u8F7D\\u6210\\u529F.')\\n          resolve(this.response);\\n        } else {\\n          logger.error('textmate onigasm file downloaded failed.')\\n          reject(new Error('Could not fetch onigasm'));\\n        }\\n      }\\n    };\\n\\n    request.open('GET', onigasmPath, true);\\n    request.responseType = 'arraybuffer';\\n    request.send();\\n  });\\n}\\nclass OnigasmLib implements IOnigLib {\\n  createOnigScanner(sources: string[]): OnigScanner {\\n    return new OnigScanner(sources);\\n  }\\n  createOnigString(sources: string): OnigString {\\n    return new OnigString(sources);\\n  }\\n}\\n\")), mdx(\"p\", null, \"\\u81F3\\u6B64\\u6211\\u4EEC\\u5B8C\\u6210\\u4E86\\u57FA\\u672C\\u7684 textmate \\u51E0\\u4E2A\\u91CD\\u8981\\u7684\\u6B65\\u9AA4\\uFF0C\\u8FD9\\u4E9B\\u6B65\\u9AA4\\u5F88\\u96BE\\u5728\\u7F51\\u4E0A\\u627E\\u5230\\uFF0C\\u76F8\\u5173\\u903B\\u8F91\\u4E00\\u822C\\u4E5F\\u4E0D\\u662F\\u7279\\u522B\\u6E05\\u695A\\uFF0C\\u597D\\u5728\\u6700\\u7EC8\\u8FD8\\u662F\\u5B9E\\u73B0\\u4E86 textmate \\u5185\\u6838\\u7684\\u52A0\\u8F7D\\u3002\"), mdx(\"h3\", null, \"3. \\u9AD8\\u4EAE\\u4E3B\\u9898\\u7684\\u4F7F\\u7528\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u76F4\\u63A5\\u62F7\\u8D1D VSCode \\u7684\\u4E3B\\u9898\\u914D\\u7F6E\\nconst dark_plus = require('./theme/vscode/dark_plus.json')\\nconst dark_defaults = require('./theme/vscode/dark_defaults.json')\\nconst dark_vs = require('./theme/vscode/dark_vs.json')\\nconst light_plus = require('./theme/vscode/light_plus.json')\\nconst light_defaults = require('./theme/vscode/light_defaults.json')\\nconst light_vs = require('./theme/vscode/light_vs.json')\\n\\n// \\u7B80\\u5355\\u5B9E\\u73B0\\u4E00\\u4E2A\\u4E3B\\u9898\\u7BA1\\u7406\\u529F\\u80FD\\uFF08MonacoThemeRegistry \\u662F theia \\u4E2D\\u7684\\u4E00\\u4E2A\\u5B9E\\u73B0\\uFF0C\\u76F4\\u63A5\\u62FF\\u6765\\u7528\\u4E86\\uFF09\\nexport const monacoThemeRegistry = new MonacoThemeRegistry();\\n\\nexport const DARK_DEFAULT_THEME: string = monacoThemeRegistry.register(\\n  dark_plus,\\n  {\\n    './dark_defaults.json': dark_defaults,\\n    './dark_vs.json': dark_vs\\n  },\\n  'dark-plus',\\n  'vs-dark'\\n).name!;\\n\\nconst currentEditorTheme = DARK_DEFAULT_THEME\\n\\n// \\u5C06\\u9ED8\\u8BA4\\u7684\\u4E3B\\u9898\\u5E94\\u7528\\ndocument.body.classList.add(currentEditorTheme);\\nmonaco.editor.setTheme(currentEditorTheme);\\n\")), mdx(\"p\", null, \"\\u8FD9\\u5757\\u4E0D\\u7EC6\\u8BF4\\u4E86\\uFF0C\\u5C06 VSCode \\u7684\\u4E3B\\u9898\\u6587\\u4EF6\\u7B80\\u5355\\u8F6C\\u6362\\u4E3A monaco-editor \\u7684\\u4E3B\\u9898\\u3002\"), mdx(\"h3\", null, \"4. \\u8BED\\u6CD5\\u7684\\u6CE8\\u518C\"), mdx(\"p\", null, \"\\u4F7F\\u7528\\u5230\\u4E86\\u90A3\\u4E2A\\u8BED\\u8A00\\uFF0C\\u518D\\u53BB\\u6CE8\\u518C\\u5177\\u4F53\\u7684\\u8BED\\u6CD5\\u89E3\\u6790\\uFF0C\\u66F4\\u597D\\u4E9B\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u5728\\u7528\\u5230\\u5BF9\\u5E94\\u8BED\\u8A00\\u624D\\u4F1A\\u6FC0\\u6D3B\\u5BF9\\u5E94\\u7684\\u8BED\\u8A00\\nfor (const { id } of monaco.languages.getLanguages()) {\\n  monaco.languages.onLanguage(id, () => activateLanguage(id));\\n}\\n\")), mdx(\"p\", null, \"\\u5177\\u4F53\\u7684\\u8BED\\u6CD5\\u5206\\u6790\\u5B9E\\u4F8B\\u5316\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u6FC0\\u6D3B\\u8BED\\u8A00\\u652F\\u6301\\nconst _activatedLanguages = new Set<string>();\\nconst activateLanguage = async (languageId: string): Promise<void> => {\\n  // \\u7F13\\u5B58\\u5DF2\\u7ECF\\u6253\\u5F00\\u7684\\u8BED\\u8A00\\n  if (_activatedLanguages.has(languageId)) return;\\n  _activatedLanguages.add(languageId);\\n\\n  // \\u770B textmate \\u662F\\u5426\\u6CE8\\u518C\\u4E86\\u5BF9\\u5E94\\u7684\\u8BED\\u6CD5\\n  const scopeName = textmateRegistry.getScope(languageId);\\n  if (!scopeName) return;\\n\\n  // \\u770B textmate \\u662F\\u5426\\u63D0\\u4F9B\\u4E86\\u4E86\\u5BF9\\u5E94\\u7684 provider\\n  const provider = textmateRegistry.getProvider(scopeName);\\n  if (!provider) return;\\n\\n  // \\u83B7\\u53D6\\u8BED\\u6CD5\\u914D\\u7F6E\\n  const configuration = textmateRegistry.getGrammarConfiguration(languageId);\\n  const initialLanguage = monaco.languages.getEncodedLanguageId(languageId)\\n\\n  await onigasmPromise;\\n  try {\\n    // \\u5B9E\\u4F8B\\u5316\\u4E00\\u4E2A\\u8BED\\u6CD5\\u5206\\u6790\\u5668\\n    const grammar = await grammarRegistry.loadGrammarWithConfiguration(scopeName, initialLanguage, configuration);\\n    const options = configuration.tokenizerOption ? configuration.tokenizerOption : TokenizerOption.DEFAULT;\\n\\n    // \\u5C06\\u8BED\\u6CD5\\u5206\\u6790\\u5668\\u6302\\u8F7D\\u5230 monaco-editor \\u63D0\\u4F9B\\u89E3\\u6790\\u670D\\u52A1\\n    monaco.languages.setTokensProvider(languageId, createTextmateTokenizer(grammar, options));\\n  } catch (error) {\\n    logger.warn('No grammar for this language id ' + languageId);\\n    console.warn(error);\\n  }\\n\\n  logger.info('\\u5F00\\u542F\\u8BED\\u8A00 ' + languageId + '\\u652F\\u6301')\\n}\\n\")), mdx(\"p\", null, \"\\u7136\\u540E\\u5C31\\u53EF\\u4EE5\\u5C1D\\u8BD5\\u662F\\u5426\\u51FA\\u73B0\\u4E86 textmate \\u89E3\\u6790\\u51FA\\u6765\\u7684\\u8BED\\u6CD5\\u9AD8\\u4EAE\\u4E86\"), mdx(\"h2\", null, \"\\u4E94\\u3001\\u7ED3\\u8BBA\"), mdx(\"p\", null, \"\\u8FD9\\u5757\\u7684\\u5B9E\\u73B0\\u521A\\u5F00\\u59CB\\u975E\\u5E38\\u8270\\u96BE\\uFF0C\\u77E5\\u9053 vscode-textmate\\uFF0C\\u4F46\\u662F\\u6CA1\\u6709\\u548C monaco-editor \\u7ED3\\u5408\\uFF0C\\u6240\\u4EE5\\u4E00\\u5934\\u96FE\\u6C34\\u3002\\u76F4\\u5230\\u6DF1\\u5165\\u5206\\u6790 theia \\u7684\\u6E90\\u7801\\u624D\\u77E5\\u9053\\u4EC0\\u4E48\\u4E2A\\u6D41\\u7A0B\\u548C\\u6982\\u5FF5\\u3002\"), mdx(\"p\", null, \"\\u597D\\u5728\\u6700\\u540E\\u7684\\u7ED3\\u679C\\u8FD8\\u662F\\u5F88\\u597D\\u7684\\uFF0C\\u76F8\\u6BD4 monaco-editor \\u81EA\\u5E26\\u7684\\u8BED\\u6CD5\\u9AD8\\u4EAE\\u7B80\\u76F4\\u9AD8\\u7EA7\\u611F\\u6EE1\\u6EE1\\uFF0C\\u548C VSCode \\u7684\\u9AD8\\u4EAE\\u903B\\u8F91\\u4E00\\u6A21\\u4E00\\u6837~~\"));\n}\n;\nMDXContent.isMDXComponent = true;"},"next":{"fileAbsolutePath":"E:/u-codes/storybok/content/blog/workpad/workpad-part-3.md","id":"1eb865bd-0120-53d7-84cc-6727f56add73","parent":{"name":"workpad-part-3","sourceInstanceName":"blog"},"excerpt":"一方面说怎么集成 monaco-editor 到项目中，另一方面怎么用扩展的形式加入新功能。 PS: 本文集成 monaco-editor 不是普遍适用的，包含很多针对当前项目的集成，所以仅供参考。 一、monaco-editor 是什么？ monaco-editor 是一个非常优秀的代码编辑器，大名鼎鼎的 VSCode 的编辑器内核，有非常强大的 IDE 功能支持。也正是有了这个优秀的工具才让浏览器编辑器成为了现实。 monaco-editor 准确的讲是从 VSCode…","fields":{"title":"🌋 WebIDE 的开发记录其三（editor 集成）","slug":"/blog/workpad-part-3","description":"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第三篇文章，谈谈 monaco-editor 的集成的。","date":"2020-01-19","redirects":null,"datetime":"2020-01-19 21:00:41","categories":["webide"],"series":"WebIDE 的开发记录","tags":["思考","整理","WorkPad","WebIDE","云开发","在线编辑器"],"status":"online"},"frontmatter":{"published":null,"tags":["思考","整理","WorkPad","WebIDE","云开发","在线编辑器"],"theme":null,"slug":"workpad-part-3","date":"2020-01-19 21:00:41"},"body":"const _excluded = [\"components\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }\n/* @jsx mdx */\n\nconst _frontmatter = {\n  \"slug\": \"workpad-part-3\",\n  \"title\": \"🌋 WebIDE 的开发记录其三（editor 集成）\",\n  \"date\": \"2020-01-19 21:00:41\",\n  \"author\": \"Ubug\",\n  \"description\": \"WorkPad 是一个非常有意思的项目，花了很多空闲时间打磨，光基础架构的重构就好几遍，现在略微记录下开发的思路和想法。本文为第三篇文章，谈谈 monaco-editor 的集成的。\",\n  \"series\": \"WebIDE 的开发记录\",\n  \"categories\": [\"webide\"],\n  \"tags\": [\"思考\", \"整理\", \"WorkPad\", \"WebIDE\", \"云开发\", \"在线编辑器\"],\n  \"banner\": \"./WorkPad-demo.png\"\n};\nconst makeShortcode = name => function MDXDefaultShortcode(props) {\n  console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n  return mdx(\"div\", props);\n};\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n      components\n    } = _ref,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"\\u4E00\\u65B9\\u9762\\u8BF4\\u600E\\u4E48\\u96C6\\u6210 monaco-editor \\u5230\\u9879\\u76EE\\u4E2D\\uFF0C\\u53E6\\u4E00\\u65B9\\u9762\\u600E\\u4E48\\u7528\\u6269\\u5C55\\u7684\\u5F62\\u5F0F\\u52A0\\u5165\\u65B0\\u529F\\u80FD\\u3002\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"PS: \\u672C\\u6587\\u96C6\\u6210 monaco-editor \\u4E0D\\u662F\\u666E\\u904D\\u9002\\u7528\\u7684\\uFF0C\\u5305\\u542B\\u5F88\\u591A\\u9488\\u5BF9\\u5F53\\u524D\\u9879\\u76EE\\u7684\\u96C6\\u6210\\uFF0C\\u6240\\u4EE5\\u4EC5\\u4F9B\\u53C2\\u8003\\u3002\")), mdx(\"h2\", null, \"\\u4E00\\u3001monaco-editor \\u662F\\u4EC0\\u4E48\\uFF1F\"), mdx(\"p\", null, \"monaco-editor \\u662F\\u4E00\\u4E2A\\u975E\\u5E38\\u4F18\\u79C0\\u7684\\u4EE3\\u7801\\u7F16\\u8F91\\u5668\\uFF0C\\u5927\\u540D\\u9F0E\\u9F0E\\u7684 VSCode \\u7684\\u7F16\\u8F91\\u5668\\u5185\\u6838\\uFF0C\\u6709\\u975E\\u5E38\\u5F3A\\u5927\\u7684 IDE \\u529F\\u80FD\\u652F\\u6301\\u3002\\u4E5F\\u6B63\\u662F\\u6709\\u4E86\\u8FD9\\u4E2A\\u4F18\\u79C0\\u7684\\u5DE5\\u5177\\u624D\\u8BA9\\u6D4F\\u89C8\\u5668\\u7F16\\u8F91\\u5668\\u6210\\u4E3A\\u4E86\\u73B0\\u5B9E\\u3002\"), mdx(\"p\", null, \"monaco-editor \\u51C6\\u786E\\u7684\\u8BB2\\u662F\\u4ECE VSCode \\u7684\\u6E90\\u7801\\u4E2D\\u5355\\u72EC\\u62BD\\u79BB\\u51FA\\u6765\\u80FD\\u591F\\u76F4\\u63A5\\u5728\\u6D4F\\u89C8\\u5668\\u4E0A\\u8FD0\\u884C\\uFF0C\\u5F88\\u591A\\u5730\\u65B9\\u548C VSCode \\u7684\\u5B9E\\u73B0\\u5E76\\u4E0D\\u76F8\\u540C\\uFF0C\\u4E0D\\u8FC7\\u7F16\\u8F91\\u5668\\u672C\\u8EAB\\u7684\\u4F53\\u9A8C\\u5927\\u90E8\\u5206\\u662F\\u4E92\\u901A\\u7684\\u3002\"), mdx(\"h2\", null, \"\\u4E8C\\u3001\\u96C6\\u6210\"), mdx(\"p\", null, \"WorkPad \\u9879\\u76EE\\u4E2D\\u7F16\\u8F91\\u5668\\u7684\\u96C6\\u6210\\u4E0D\\u53EF\\u80FD\\u7B80\\u5355\\u4E00\\u7BC7\\u6587\\u7AE0\\u8BF4\\u5F97\\u6E05\\u695A\\uFF0C\\u8FD9\\u91CC\\u53EA\\u662F\\u6700\\u57FA\\u7840\\u503C\\u5F97\\u8BF4\\u7684\\u65B9\\u9762\"), mdx(\"h3\", null, \"0. \\u5F15\\u5165\"), mdx(\"p\", null, \"\\u4F7F\\u7528 rquire \\u7684\\u65B9\\u5F0F\\u52A0\\u8F7D AMD \\u6807\\u51C6\\u6A21\\u5757\\u7684\\u5E93\\uFF0C\\u800C\\u4E0D\\u662F\\b\\u7528 ESM \\u6A21\\u5757\\u6807\\u51C6\\u4EA4\\u7ED9 webpack \\u6253\\u5305\\uFF0C\\u6BD5\\u7ADF\\u8FD9\\u4E2A\\u5185\\u6838\\u86EE\\u5927\\u7684\\uFF0C\\u8FD9\\u6837\\u505A\\u6BD4\\u8F83\\u7075\\u6D3B\\uFF0C\\u591A\\u8BED\\u8A00\\u3001worker \\u4E4B\\u7C7B\\u7684\\u4E0D\\u9700\\u8981\\u8D39\\u795E\\u914D\\u7F6E\\uFF0C\\u540E\\u7EED\\u7684\\u5185\\u90E8\\u6A21\\u5757\\u5F15\\u7528\\u4E5F\\u53EF\\u4EE5\\u4F7F\\u7528 \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"require\"), \" \\u6765\\u83B7\\u53D6\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-html\"\n  }, \"<script src=\\\"/public/vs/loader.js\\\"></script>\\n<script>\\n  require.config({\\n    paths: {\\n      'vs': '/public/vs'\\n    },\\n    'vs/nls': {\\n      availableLanguages: {\\n        '*': 'zh-cn'\\n      }\\n    }\\n  });\\n  // ubug: \\u786E\\u4FDD monaco \\u52A0\\u8F7D\\u6210\\u529F\\u624D\\u80FD\\u8C03\\u7528\\u5B9E\\u9645\\u529F\\u80FD\\n  window.require(['vs/editor/editor.main'], function (editor) {\\n    console.log('monaco-editor \\u52A0\\u8F7D\\u6210\\u529F')\\n\\n    var n = document.createElement('script');\\n    n.type = 'text/javascript';\\n    n.src = 'index.js';\\n    document.body.appendChild(n);\\n    n.onload = ()=> {\\n      console.log('\\u4E3B\\u903B\\u8F91\\u52A0\\u8F7D\\u6210\\u529F')\\n    }\\n  });\\n</script>\\n\")), mdx(\"h3\", null, \"1. \\u4E8B\\u5148\\u914D\\u7F6E\"), mdx(\"p\", null, \"\\u914D\\u7F6E monaco \\u9ED8\\u8BA4\\u914D\\u7F6E\\uFF0C\\u76D1\\u542C editor \\u521B\\u5EFA\\u540E\\u914D\\u7F6E\\u7B49\\u64CD\\u4F5C:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"function bindTextmate() {\\n  // ......\\n  monaco.editor.setTheme(currentEditorTheme);\\n  \\n  for (const { id } of monaco.languages.getLanguages()) {\\n    monaco.languages.onLanguage(id, () => activateLanguage(id));\\n  }\\n}\\nconst dirtyManager = new DirtyDiffManager()\\n\\nfunction configureMonaco() {\\n  bindTextmate(); // \\u914D\\u7F6E\\u8BED\\u6CD5\\u9AD8\\u4EAE\\u7B49\\n  // ... bind other things\\n}\\nfunction configureEditor(editor: monaco.editor.IStandaloneCodeEditor) {\\n  dirtyManager.start(editor) // \\u914D\\u7F6E git diff \\u903B\\u8F91\\n}\\n\\nconfigureMonaco();\\nmonaco.editor.onDidCreateEditor(configureEditor);\\n\")), mdx(\"h3\", null, \"2. \\u521D\\u59CB\\u5316\\u4E00\\u4E2A\\u7F16\\u8F91\\u5668\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"// \\u672C\\u6765\\u662F\\nlet editorOverrides = {\\n  editorService: {\\n    // openEditor: function () {\\n    //   alert(`open editor called!` + JSON.stringify(arguments));\\n    // },\\n    // resolveEditor: function () {\\n    //   alert(`resolve editor called!` + JSON.stringify(arguments));\\n    // }\\n  }\\n}\\n\\nlet options: monaco.editor.IEditorOptions = {\\n  minimap: {\\n    enabled: true,\\n    showSlider: 'always',\\n    renderCharacters: false\\n  },\\n  glyphMargin: true,\\n  lightbulb: {\\n    enabled: true\\n  },\\n  extraEditorClassName: '__ubug_monaco',\\n};\\n\\nconst defaultModel = monaco.editor.createModel('', 'plaintext');\\nconst editor = monaco.editor.create(this.el, { ...options, model: defaultModel }, editorOverrides);\\n\")), mdx(\"p\", null, \"\\u5176\\u4E2D \\u7B2C\\u4E09\\u4E2A\\u53C2\\u6570 OverrideServices \\u76EE\\u7684\\u662F\\u8986\\u76D6\\u5185\\u7F6E\\u7684\\u4E00\\u4E9B\\u670D\\u52A1\\uFF0C\\u6BD4\\u5982\\u8DF3\\u8F6C\\u5230\\u6216\\u8005\\u5F15\\u7528\\u7B49\\u529F\\u80FD\\uFF0C\\u5728\\u67D0\\u4E9B\\u7248\\u672C\\u4E2D\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/microsoft/monaco-editor/issues/291#issuecomment-450709332\"\n  }, \"\\u53EF\\u80FD\\u4F1A\\u88AB\\u8986\\u76D6\\u5BFC\\u81F4\\u5931\\u6548\"), \"\\uFF0C\\u53EF\\u4EE5\\u901A\\u8FC7\\u76F8\\u5BF9 hack \\u7684\\u65B9\\u5F0F\\u6DFB\\u52A0\\u529F\\u80FD\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"\\nfunction hackOverides(editor: monaco.editor.IStandaloneCodeEditor) {\\n  // @ts-ignore\\n  const services = [...editor._instantiationService._parent._services._entries.values()];\\n  const textModelService = services.find((service) => {\\n    const props = Object.getPrototypeOf(service)\\n    return props && 'createModelReference' in props\\n  });\\n\\n  // @ts-ignore\\n  const codeEditorService = editor._codeEditorService;\\n  codeEditorService.openCodeEditor = (input: { resource: monaco.Uri, options: any }) => {\\n    const { resource, options } = input\\n    const file = resource.path;\\n    const range = options.selection;\\n    // Add code here to open the code editor.\\n\\n    const states = window._novus.models.workspace.state\\n    let path = file.replace(states.config.path, '')\\n\\n    commandsPool.writer.openFile.trigger(path, () => {\\n      window._novus.models.writer.state.currentEditor.setSelection(range);\\n      window._novus.models.writer.state.currentEditor.revealLineInCenter(range.startLineNumber);\\n    });\\n  }\\n\\n\\n  textModelService.createModelReference = async (uri: monaco.Uri) => {\\n\\n    const fileManagerModel = window._novus.models[\\\"fileManager\\\"]\\n\\n    const states = window._novus.models.workspace.state\\n    let fileId = uri.path.replace(states.config.path, '')\\n    let model = modelsHolder.models[fileId];\\n\\n    if (!model) {\\n      let file = await fileManagerModel.actions.queryFile(fileId);\\n      const contentsMap = fileManagerModel.state.contentsMap\\n      const content = contentsMap[fileId];\\n      const language = getLang(`.${fileId.split('.').pop()}`)\\n\\n      if (file) {\\n        await fileManagerModel.actions.fetchFileContent(fileId);\\n        modelsHolder.addModel(file.relative, file.path, content, language);\\n        model = modelsHolder.models[fileId];\\n      }\\n    }\\n\\n    const reference = {\\n      load() {\\n        return Promise.resolve(model.model)\\n      },\\n      // in my case, I have nothing to dispose as I just re-use existing resources\\n      dispose() { },\\n      textEditorModel: model.model\\n    }\\n    return {\\n      object: reference,\\n      dispose() { },\\n    };\\n  };\\n}\\n\\nhackOverides(editor);\\n\")), mdx(\"p\", null, \"\\u5728\\u6DFB\\u52A0 LSP \\u529F\\u80FD\\u6216\\u8005\\u672C\\u5730 model \\u8DEF\\u5F84\\u5B8C\\u6574\\u7684\\u60C5\\u51B5\\u4E0B\\uFF0C\\u652F\\u6301\\u8DF3\\u8F6C\\u548C\\u5F15\\u7528\\u67E5\\u770B\\u3002\"), mdx(\"h3\", null, \"3. \\u5206\\u522B\\u50A8\\u5B58 model \\u548C state \\u6765\\u5B9E\\u73B0\\u591A\\u6587\\u4EF6\\u7F16\\u8F91\"), mdx(\"p\", null, \"\\u5728 IDE \\u6982\\u5FF5\\u4E2D\\u4E0D\\u53EF\\u80FD\\u6BCF\\u6B21\\u7F16\\u8F91\\u6587\\u4EF6\\u90FD\\u521B\\u5EFA\\u4E00\\u4E2A editor\\uFF0C\\u6240\\u4EE5\\u63D0\\u4F9B\\u4E86 model \\u548C state \\u7684\\u529F\\u80FD\\u6765\\u50A8\\u5B58\\u6587\\u4EF6\\u7684\\u6A21\\u578B\\u548C\\u72B6\\u6001\\u3002\"), mdx(\"p\", null, \"model \\u8868\\u793A\\u4E00\\u4E2A\\u7F16\\u8F91\\u6587\\u4EF6\\u7684\\u5FEB\\u7167\\uFF0C\\u5305\\u542B\\u6587\\u4EF6\\u4FE1\\u606F\\u3001\\u8BED\\u8A00\\u6807\\u8BB0\\u3001\\u914D\\u7F6E\\u3001\\u88C5\\u9970\\u4FE1\\u606F\\u7B49\\uFF0C\\u53EF\\u4EE5\\u4F7F\\u7528 getModel \\u548C setModel \\u5207\\u6362\\u4E0D\\u540C\\u7684\\u6587\\u4EF6\\u3002state \\u8868\\u793A\\u89C6\\u56FE\\u4E0A\\u7684\\u72B6\\u6001\\uFF0C\\u6BD4\\u5982\\u5149\\u6807\\u72B6\\u6001\\u3001\\u6EDA\\u52A8\\u4F4D\\u7F6E\\u7B49\\u4FE1\\u606F\\u3002\"), mdx(\"p\", null, \"\\u6839\\u636E\\u8FD9\\u4E24\\u4E2A\\u4FE1\\u606F\\u6765\\u652F\\u6301\\u591A\\u6587\\u4EF6\\u7684\\u7F16\\u8F91\\u548C\\u5207\\u6362\\u529F\\u80FD\\uFF0C\\u6211\\u5728\\u9879\\u76EE\\u4E2D\\u4F7F\\u7528\\u4E86\\u4E00\\u4E2A modelManager \\u6765\\u5355\\u72EC\\u5904\\u7406\\u6587\\u4EF6\\u5185\\u5BB9\\u3001\\u6587\\u4EF6\\u72B6\\u6001\\u3001\\u7F16\\u8F91\\u72B6\\u6001\\u4E4B\\u7C7B\\u7684\\uFF0C\\u53EF\\u4EE5\\u6839\\u636E\\u903B\\u8F91\\u7075\\u6D3B\\u7684\\u591A\\u6587\\u4EF6\\u5207\\u6362\\u3002\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"// \\u83B7\\u53D6\\u5E76\\u5B58\\u50A8\\nlet model = this.editor.getModel();\\nlet state = this.editor.saveViewState();\\nmodelsManager.updateModeler({ id: currentTabId, model, state})\\n\\n// \\u6062\\u590D\\nlet targetModel = modelsManager.models[tabId];\\nthis.editor.setModel(targetModel.model);\\nthis.editor.restoreViewState(targetModel.state);\\n\")), mdx(\"h3\", null, \"4. \\u5468\\u8FB9\\u914D\\u7F6E\"), mdx(\"p\", null, \"\\u5E38\\u89C1\\u7684\\u4E00\\u4E9B\\u914D\\u7F6E\\u6BD4\\u5982 \\u7F29\\u8FDB\\u3001\\u7A7A\\u683C\\u3001\\u884C\\u5217\\u9009\\u62E9\\u3001\\u8BED\\u8A00\\u3001\\u6362\\u884C\\u6A21\\u5F0F\\u3001\\u6587\\u4EF6\\u5927\\u5C0F\\u7B49\\u4FE1\\u606F\\uFF0C\\u6BD4\\u5982\\u7F29\\u8FDB\\uFF1A\"), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"283px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/90393f6ae3fe4c91ff41fcb311fc7970/f9369/indent-show.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"9.266409266409267%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsSAAALEgHS3X78AAAAkUlEQVQI12NwK17637FgMRhbZi34rxo9HUxrxM38r588Byxulb3gv17SbDA/pHb1f7vcRf91Emf/1wVikBxI3KlgyX/L7IX/GSLadv4Patr2P6x1x3+/+q3/NVKW/ncq2/BfK3Xpf7O81f9dKjYC8Yb/xjkr/5vnr/6fMekAWJ1h1gqwGEjONHfVf1+gmAVQHgDSKFz5bcQTawAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"配置展示\",\n    \"title\": \"配置展示\",\n    \"src\": \"/static/90393f6ae3fe4c91ff41fcb311fc7970/f9369/indent-show.png\",\n    \"srcSet\": [\"/static/90393f6ae3fe4c91ff41fcb311fc7970/ae269/indent-show.png 259w\", \"/static/90393f6ae3fe4c91ff41fcb311fc7970/f9369/indent-show.png 283w\"],\n    \"sizes\": \"(max-width: 283px) 100vw, 283px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u914D\\u7F6E\\u5C55\\u793A\"), \"\\n  \")), mdx(\"p\", null, \"\\u5728\\u72B6\\u6001\\u680F\\u5C55\\u793A\\u90E8\\u5206\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"const IndentWidget = () => {\\n  let state = useNovus<TState>((models) => {\\n    const activeId = models.layout.state.layout.dealer.activeId;\\n    return {\\n      activeId: activeId,\\n      activeTab: models.writer.state.tabs[activeId],\\n    };\\n  }, ['workspace', 'writer'])\\n\\n  const model = modelsHolder.models[state.activeId];\\n  if (!model || !state.activeTab || state.activeTab.type !== 'text') return null;\\n  const options = model.model.getOptions();\\n  const space = options.insertSpaces;\\n  const tabSize = options.tabSize;\\n\\n  return <Tooltip title=\\\"\\u4FEE\\u6539\\u7F29\\u8FDB\\\">\\n    <CommandBtn command=\\\"writer.changeIndent\\\">\\n      {`${space ? '\\u7A7A\\u683C' : 'Tab'}: ${space ? tabSize : null}`}\\n    </CommandBtn>\\n  </Tooltip>\\n}\\n\")), mdx(\"p\", null, mdx(\"figure\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-figure\",\n    \"style\": {}\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"640px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/e4a91575e872b9464a4cca9d21b1eb64/0cc36/indent-change.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": [\"noopener\"]\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"45.173745173745175%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsSAAALEgHS3X78AAABD0lEQVQoz52QTU+EMBRFWU105cIYILQdPoxGWgYzQDUBWoYxUdnorHTH//8V19aOmZUJujjp4r2e3Pu8m7sN7muNsuoMPSqp/0VZKdwal8flDpvnGdU0Y/s6I3o4IJTvCJu3RQQG8nhA+TIjyAp4JK8Qjx+43ls+cVlPOBdPWOUjVnx0728c52d8j4vthKs0hxfHMbpeoVcaWg8QokCSJKCMgbG1gS2CEGogTtg0NaSUKIQwQ4q1WaCUgi3E7kZRdBL2SkGZhG3bgnNxTLaAtWsQm0b2nxU7Yd9/03UdhmGHLMtcwgVV7Z51cM6d0N5LmYRWprVLmabpYuHphsRV/ulusQPf9xEEAcIw/DPW9QW1WAbRTUyemgAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"状态栏点击修改\",\n    \"title\": \"状态栏点击修改\",\n    \"src\": \"/static/e4a91575e872b9464a4cca9d21b1eb64/0cc36/indent-change.png\",\n    \"srcSet\": [\"/static/e4a91575e872b9464a4cca9d21b1eb64/ae269/indent-change.png 259w\", \"/static/e4a91575e872b9464a4cca9d21b1eb64/a4dff/indent-change.png 518w\", \"/static/e4a91575e872b9464a4cca9d21b1eb64/0cc36/indent-change.png 640w\"],\n    \"sizes\": \"(max-width: 640px) 100vw, 640px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), \"\\n    \", mdx(\"figcaption\", {\n    parentName: \"figure\",\n    \"className\": \"gatsby-resp-image-figcaption\"\n  }, \"\\u72B6\\u6001\\u680F\\u70B9\\u51FB\\u4FEE\\u6539\"), \"\\n  \")), mdx(\"p\", null, \"\\u70B9\\u51FB\\u7684\\u547D\\u4EE4\\uFF0C\\u652F\\u6301\\u4F7F\\u7528 monaco-editor \\u81EA\\u5E26\\u7684 quickOpen \\u529F\\u80FD\\u5C55\\u793A\\u914D\\u7F6E\\u9009\\u9879\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { getModel } from '.';\\n\\nconst { QuickOpenModel, QuickOpenEntryGroup } = window.require('vs/base/parts/quickopen/browser/quickOpenModel');\\nconst { BaseEditorQuickOpenAction } = window.require('vs/editor/standalone/browser/quickOpen/editorQuickOpen');\\nconst { matchesFuzzy } = window.require('vs/base/common/filters');\\nconst { Range } = window.require('vs/editor/common/core/range');\\n\\ntype TActionOption = {\\n  withBorder?: boolean\\n  group?: string\\n}\\n\\nfunction getIndentationEditOperations(model: monaco.editor.ITextModel, tabSize: number, tabsToSpaces: boolean) {\\n  if (model.getLineCount() === 1 && model.getLineMaxColumn(1) === 1) { return; }\\n  let spaces = ' '.repeat(tabSize);\\n  let spacesRegExp = new RegExp(spaces, 'gi');\\n  let operations = [];\\n\\n  for (let lineNumber = 1, lineCount = model.getLineCount(); lineNumber <= lineCount; lineNumber++) {\\n    let lastIndentationColumn = model.getLineFirstNonWhitespaceColumn(lineNumber) || model.getLineMaxColumn(lineNumber);\\n    if (lastIndentationColumn === 1) continue;\\n\\n    const originalIndentationRange = new Range(lineNumber, 1, lineNumber, lastIndentationColumn);\\n    const originalIndentation = model.getValueInRange(originalIndentationRange);\\n    const newIndentation = (tabsToSpaces ? originalIndentation.replace(/\\\\t/ig, spaces) : originalIndentation.replace(spacesRegExp, '\\\\t'));\\n    operations.push({\\n      range: originalIndentationRange,\\n      text: newIndentation\\n    });\\n  }\\n  model.applyEdits(operations);\\n}\\n\\nclass DemoActionCommandEntry extends QuickOpenEntryGroup {\\n  constructor(highlights: any, editor: monaco.editor.IStandaloneCodeEditor, option: TActionOption) {\\n    super();\\n    this.editor = editor;\\n    this.option = option;\\n    this.withBorder = option.withBorder;\\n    return this;\\n  }\\n  getLabel =  () => this.option.label;\\n  getAriaLabel =  () => this.option.label;\\n  getDetail =  () => this.option.desc;\\n  getGroupLabel =  () => this.option.group || '';\\n\\n  run = (mode: number) => {\\n    if (mode === 1 /* OPEN */) {\\n      var model = getModel(this.editor);\\n\\n      if (this.option.operate[0] === 0) {\\n        if (this.option.operate[1] === 0) {\\n          model.updateOptions({\\n            tabSize: this.option.operate[2],\\n            insertSpaces: true\\n          });\\n        } else {\\n          model.updateOptions({\\n            insertSpaces: false\\n          });\\n        }\\n      } else {\\n        let modelOpts = model.getOptions();\\n        // \\u8F6C\\u6362 model, builder, tabSize, tabsToSpaces\\n        getIndentationEditOperations(model, modelOpts.tabSize, this.option.operate[1] === 0)\\n      }\\n\\n      return true;\\n    }\\n    return false;\\n  };\\n}\\n\\nexport class IndentCommandAction extends BaseEditorQuickOpenAction {\\n  constructor() {\\n    super(\\\"ubug: \\u4FEE\\u6539\\u7F29\\u8FDB\\\", {\\n      id: 'editor.ubug.changeIndent',\\n      label: \\\"ubug: \\u4FEE\\u6539\\u7F29\\u8FDB\\\",\\n      alias: 'ubug: \\u4FEE\\u6539\\u7F29\\u8FDB',\\n      // menuOpts: {}\\n      menuOpts: null\\n    })\\n    return this;\\n  }\\n  run = function (accessor: any, editor: monaco.editor.IStandaloneCodeEditor) {\\n    this._show(this.getController(editor), {\\n      getModel: function (value: string) {\\n        var entries = [\\n          {\\n            label: '\\u4F7F\\u7528 2 \\u7A7A\\u683C\\u7F29\\u8FDB',\\n            group: '\\u89C6\\u56FE',\\n            desc: 'Indent Using 2 Spaces',\\n            operate: [0, 0, 2] // insertSpaces, space nums\\n          },\\n          {\\n            label: '\\u4F7F\\u7528 4 \\u7A7A\\u683C\\u7F29\\u8FDB',\\n            desc: 'Indent Using 4 Spaces',\\n            operate: [0, 0, 4]\\n          },\\n          {\\n            label: '\\u4F7F\\u7528 Tab \\u7F29\\u8FDB',\\n            desc: 'Indent Using Tab',\\n            operate: [0, 1, 2]\\n          },\\n          {\\n            label: '\\u4F7F\\u7528\\u7A7A\\u683C\\u8F6C\\u6362\\u5DF2\\u6709\\u5185\\u5BB9',\\n            group: '\\u8F6C\\u6362',\\n            desc: 'Indent Using 2 Spaces',\\n            operate: [1, 0], // insertSpaces, space nums\\n            withBorder: true\\n          },\\n          {\\n            label: '\\u4F7F\\u7528 Tab \\u8F6C\\u6362\\u5DF2\\u6709\\u5185\\u5BB9',\\n            desc: 'Indent Using Tab',\\n            operate: [1, 1]\\n          },\\n        ];\\n        var models = entries.filter(e => (matchesFuzzy(value, e.label) || matchesFuzzy(value, e.desc))).map((e) => {\\n          return new DemoActionCommandEntry(value, editor, e);\\n        })\\n        return new QuickOpenModel(models);\\n      },\\n      getAutoFocus: function (searchValue: string) {\\n        return {\\n          autoFocusFirstEntry: searchValue.length > 0,\\n          autoFocusIndex: getModel(editor).getOptions().defaultEOL - 1\\n        };\\n      }\\n    });\\n  };\\n}\\n\")), mdx(\"p\", null, \"\\u8FD9\\u4E2A\\u76F8\\u5F53\\u4E8E\\u662F\\u5C06\\u600E\\u4E48\\u5728 monaco-editor \\u7684\\u83DC\\u5355\\u4E2D\\u6DFB\\u52A0\\u81EA\\u5B9A\\u4E49\\u7684\\u9009\\u9879\\u5217\\u8868\\uFF0C\\u4E0D\\u9700\\u8981\\u81EA\\u5DF1\\u5199\\u5177\\u4F53\\u7684\\u903B\\u8F91\\uFF0C\\u529F\\u80FD\\u7684\\u63D0\\u4F9B\\u662F monaco-editor \\u81EA\\u5E26\\u7684\\uFF0C\\u975E\\u5E38\\u6709\\u8DA3\\u3002\"), mdx(\"p\", null, \"\\u5176\\u4ED6\\u7684\\u6BD4\\u5982 \\u8BED\\u8A00\\u9009\\u53D6\\u3001\\u7F16\\u7801\\u6A21\\u5F0F\\u90FD\\u53EF\\u4EE5\\u7528\\u8FD9\\u79CD\\u65B9\\u5F0F\\u6269\\u5C55\\u3002\"), mdx(\"h3\", null, \"5. \\u5176\\u4ED6\\u5468\\u8FB9\"), mdx(\"p\", null, \"LSP \\u96C6\\u6210\\u3001DirtyDiff \\u96C6\\u6210\\u3001TextMate \\u9AD8\\u4EAE\\u96C6\\u6210\\u5728\\u540E\\u9762\\u90FD\\u4F1A\\u6DF1\\u5165\\u8BF4\\u3002\"), mdx(\"h2\", null, \"\\u4E09\\u3001\\u6269\\u5C55\\u96C6\\u6210\"), mdx(\"p\", null, \"\\u96C6\\u6210\\u9700\\u8981\\u6D89\\u53CA\\u7684\\u4E1C\\u897F\\u5305\\u62EC\\u6CE8\\u518C\\u6269\\u5C55\\u3001\\u6CE8\\u518C\\u6570\\u636E\\u6A21\\u578B\\u3001\\u6CE8\\u518C command \\u52A8\\u4F5C\\u5E93\\u3001\\u6CE8\\u518C\\u72B6\\u6001\\u680F\\u3002\"), mdx(\"p\", null, \"monaco-editor \\u989D\\u5916\\u9700\\u8981\\u505A\\u7684\\u6709\\u7F16\\u8F91\\u5668\\u914D\\u7F6E\\u3001model \\u914D\\u7F6E\\u3001model \\u548C state \\u72B6\\u6001\\u62C6\\u5206\\u3001DirtyDiff \\u548C Peek \\u65B9\\u6848\\u3001\\u5F15\\u7528\\u548C\\u8DF3\\u8F6C\\u65B9\\u6848\\u3001\\u591A\\u8BED\\u8A00\\u5207\\u6362\\u4EE5\\u53CA\\u7F29\\u8FDB\\u7B49\\u9009\\u9879\\u3001textmate \\u9AD8\\u4EAE\\u65B9\\u6848\\u3001LSP \\u65B9\\u6848\\u7B49\"), mdx(\"h3\", null, \"1. \\u6269\\u5C55\\u6CE8\\u518C\"), mdx(\"p\", null, \"\\u5728\\u5185\\u6838\\u642D\\u5EFA\\u8D77\\u6765\\u4E4B\\u540E\\uFF0C\\u80FD\\u591F\\u901A\\u8FC7\\u62D3\\u5C55\\u7684\\u5F62\\u5F0F\\u5728\\u89C6\\u56FE\\u4E0A\\u7684\\u67D0\\u4E2A\\u533A\\u57DF\\u6CE8\\u518C\\u5185\\u5BB9\\uFF0C\\u6240\\u4EE5\\u6211\\u4EEC\\u53EA\\u9700\\u8981\\u5199\\u4E00\\u4E2A\\u62D3\\u5C55\\uFF0C\\u7136\\u540E\\u6309\\u7167\\u914D\\u7F6E\\u7EA6\\u5B9A\\u5199\\u4E0A\\u903B\\u8F91\\u5C31\\u80FD\\u5C06\\u7F16\\u8F91\\u5668\\u96C6\\u6210\\u8FDB\\u53BB\\u4E86\\u3002\"), mdx(\"p\", null, \"\\u7B80\\u5355\\u793A\\u4F8B\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import React from 'react';\\n\\nimport model from \\\"./model\\\";\\nimport { Extension } from '..';\\nimport Novus from '../../models';\\n\\nimport Writer from \\\"./Component\\\";\\nimport WriterTab from \\\"./Component/tab\\\";\\n\\nimport { registerStatusBar } from \\\"@utils/statusBar\\\";\\n\\nimport LineWidget     from \\\"./statusBar/LineWidget\\\";\\nimport IndentWidget   from \\\"./statusBar/IndentWidget\\\";\\nimport EncodeWidget   from \\\"./statusBar/EncodeWidget\\\";\\nimport EOLWidget      from \\\"./statusBar/EOLWidget\\\";\\nimport LanguageWidget from \\\"./statusBar/LanguageWidget\\\";\\n\\n// monaco editor addons\\nimport initEditorPlugins from './monacoPlugins/index';\\nimport configureMonaco from './afterMonaco/index';\\nimport configureEditor from './afterEditor/index';\\n\\ninitEditorPlugins();\\n\\nimport { commands } from \\\"./commands\\\";\\n\\nexport default (novus: Novus): Extension => {\\n  novus.bindModel(model);\\n\\n  commandsCenter.registerCommands(\\\"writer\\\", commands);\\n\\n  registerStatusBar({\\n    lineWidget:     { com: LineWidget },\\n    indentWidget:   { com: IndentWidget },\\n    encodeWidget:   { com: EncodeWidget },\\n    EOLWidget:      { com: EOLWidget },\\n    LanguageWidget: { com: LanguageWidget },\\n  });\\n\\n  return {\\n    id: 'writer',\\n    useSticky: 'writer-dealer',\\n    panel: Writer,\\n    tab: WriterTab,\\n    init: () => {\\n      // config Monaco and every editor\\n      configureMonaco();\\n      monaco.editor.onDidCreateEditor(configureEditor);\\n    },\\n  }\\n}\\n\")), mdx(\"p\", null, \"\\u4E0A\\u9762\\u7684\\u4EE3\\u7801\\u8868\\u793A\\u6CE8\\u518C\\u4E00\\u4E2A \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"writer\"), \" \\u7684\\u6269\\u5C55\\uFF0Ccommands \\u91CC\\u9762\\u63D0\\u4F9B\\u6253\\u5F00 tab \\u7684\\u65B9\\u6CD5\\uFF0C\\u7136\\u540E\\u5185\\u6838\\u6846\\u67B6\\u6E32\\u67D3\\u7684\\u65F6\\u5019\\uFF0C\\u4F1A\\u6839\\u636E tab \\u7684\\u7C7B\\u578B\\u8C03\\u7528\\u8FD9\\u4E2A writer \\u6765\\u6E32\\u67D3\\u754C\\u9762\\u3002\\u540C\\u65F6\\u8FD8\\u6CE8\\u518C\\u4E86\\u5E95\\u90E8\\u7684\\u72B6\\u6001\\u680F\\uFF0C\\u80FD\\u591F\\u6839\\u636E\\u5F53\\u524D\\u6253\\u5F00\\u7684\\u6587\\u4EF6\\u663E\\u793A\\u8F85\\u52A9\\u6570\\u636E\\u3002\"), mdx(\"h3\", null, \"2. \\u6570\\u636E\\u6A21\\u578B\"), mdx(\"p\", null, \"\\u4E0A\\u4E00\\u7BC7\\u6587\\u7AE0\\u5DF2\\u7ECF\\u8BF4\\u660E\\u4E86\\u6570\\u636E\\u6A21\\u578B\\u5728\\u8FD9\\u4E2A\\u9879\\u76EE\\u4E2D\\u7684\\u7528\\u6CD5\\uFF0C\\u8FD9\\u4E2A\\u6570\\u636E\\u6A21\\u578B\\u4FDD\\u5B58\\u5F53\\u524D\\u7684\\u5168\\u90E8\\u6253\\u5F00\\u6587\\u4EF6\\u4EE5\\u53CA\\u76F8\\u5173\\u64CD\\u4F5C\\u65B9\\u6CD5\\uFF1A\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"type TabConfig = {\\n  id: string;           // id \\u552F\\u4E00\\u6807\\u8BC6\\n  preview: boolean;     // \\u662F\\u5426\\u662F\\u9884\\u89C8\\u72B6\\u6001\\n  name: string;         // \\u6587\\u4EF6\\u540D\\n  type: string;         // \\u6587\\u4EF6\\u7C7B\\u578B\\uFF08\\u53EF\\u4EE5\\u662F\\u6587\\u672C\\u6587\\u4EF6\\u3001\\u56FE\\u7247\\u3001HTML \\u9884\\u89C8\\uFF09\\n  file: TFile;          // \\u6587\\u4EF6\\u7684\\u7C7B\\u578B\\uFF08\\u8FD9\\u4E2A\\u5728\\u6587\\u4EF6\\u7BA1\\u7406\\u5668\\u4E2D\\u5B9A\\u4E49\\uFF0C\\u9644\\u5E26\\u6587\\u4EF6\\u7684\\u5730\\u5740\\u3001\\u76F8\\u5BF9\\u5730\\u5740\\u3001\\u5927\\u5C0F\\u3001\\u4FEE\\u6539\\u4E8B\\u4EF6\\u3001\\u7B80\\u5355 git \\u4FE1\\u606F\\u7B49\\uFF09\\n  language: string;     // \\u6587\\u672C\\u6587\\u4EF6\\u7684\\u8BDD\\uFF0C\\u4EE3\\u7801\\u8BED\\u8A00\\n  changed: boolean;     // \\u6807\\u8BC6\\u5F53\\u524D\\u7F16\\u8F91\\u5668\\u7684\\u5185\\u5BB9\\u662F\\u5426\\u6709\\u6539\\u52A8\\n  content: string;      // \\u6682\\u5B58\\u5F53\\u524D tab \\u7684\\u6587\\u4EF6\\u5185\\u5BB9\\n  status: number;       // \\u6587\\u4EF6\\u72B6\\u6001\\n  modelReady: boolean;  // \\u662F\\u5426\\u5DF2\\u7ECF\\u6CE8\\u518C\\u4E86 editor \\u7684 model\\n  specialType?: string; // \\u662F\\u5426\\u662F\\u7279\\u6B8A\\u7C7B\\u578B\\uFF0C\\u9700\\u8981\\u7279\\u6B8A\\u6E32\\u67D3\\n}\\n\\ntype Tabs = {\\n  [index: string]: TTab;\\n}\\n\\nexport type TTabs = ImmutableObjectMixin<Tabs> & Tabs;\\nexport type TTab = ImmutableObjectMixin<TabConfig> & TabConfig;\\n\\nexport interface IWriterState {\\n  tabs: TTabs,\\n  currentEditor: monaco.editor.IStandaloneCodeEditor,\\n}\\n\\nclass WriterModel extends NovusBaseModel<IWriterState> {\\n  namespace = 'writer'\\n  constructor(){\\n    super()\\n    this.state = {\\n      tabs: Immutable({}), // \\u4F7F\\u7528\\u4E0D\\u53EF\\u53D8\\u6570\\u636E\\u7C7B\\u578B\\uFF0C\\u4F7F\\u5F97\\u6DF1\\u5C42\\u5BF9\\u8C61\\u6539\\u53D8\\u4E5F\\u80FD\\u89E6\\u53D1\\u66F4\\u65B0\\u72B6\\u6001\\n      currentEditor: null,\\n    }\\n  }\\n\\n  actions = {\\n    // ---------- tabs\\n    notifyTabClose: (tabId: string) => {\\n      // ...\\n    },\\n    editorChange: (editor: monaco.editor.IStandaloneCodeEditor) => {\\n      this.setState({ currentEditor: editor })\\n    },\\n    updateTab: <K extends keyof TabConfig>(tabId: string, data: Pick<TabConfig, K>) => {\\n      // ...\\n    },\\n    previewConfirm: (tabId: string) => {\\n      // ...\\n    },\\n    openTab: async (file: TFile, skipPreview: boolean = false) => {\\n      // ...\\n      let tab = generateTab(file, skipPreview);\\n      if (tab) {\\n        // ...\\n        await this.getModel('layout').actions.modifyPanels({\\n          adds: [\\n            {\\n              component: 'writer',\\n              id: fileId,\\n              data: { tabId: fileId },\\n              stackPosition: 'dealer'\\n            }\\n          ],\\n          removes\\n        });\\n      }\\n    },\\n  }\\n};\\nexport default new WriterModel();\\n\")), mdx(\"h3\", null, \"3. command \\u6253\\u5F00\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { getSpecialType } from \\\"./specialEditors\\\";\\nimport Immutable from \\\"seamless-immutable\\\";\\n\\nimport { TFile, TFileRaw } from \\\"../FileManager/model\\\";\\n\\nexport const commands = {\\n  gotoLine: {\\n    trigger: () => {\\n      // ...\\n    }\\n  },\\n  changeIndent: {\\n    trigger: () => {\\n      // ...\\n    }\\n  },\\n  chooseLanguage: {\\n    trigger: () => {\\n      // ...\\n    }\\n  },\\n  showSourceCode: {\\n    label: \\\"\\u67E5\\u770B\\u6E90\\u4EE3\\u7801\\\",\\n    trigger: () => {\\n      // ...\\n    }\\n  },\\n  openFile: {\\n    trigger: async (\\n      fileRelative: string,\\n      cb?: Function,\\n      skipPreview?: boolean\\n    ) => {\\n        window._novus.models[\\\"writer\\\"].actions.previewConfirm(fileId);\\n        // or ...\\n        await window._novus.models.layout.actions.activePanel(fileId);\\n        // or ...\\n        window._novus.models[\\\"writer\\\"].actions.openTab(file, skipPreview);\\n      }\\n    }\\n  },\\n  createUntitledFile: {\\n    key: [\\\"ctrl+n\\\"],\\n    label: \\\"\\u65B0\\u5EFA\\u6587\\u4EF6\\\",\\n    trigger: () => {\\n      // ...\\n    }\\n  }\\n};\\n\")));\n}\n;\nMDXContent.isMDXComponent = true;"}}}}